neoagent 2.1.17-beta.2 → 2.1.17-beta.21

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.
Files changed (54) hide show
  1. package/docs/configuration.md +1 -1
  2. package/package.json +8 -4
  3. package/server/db/database.js +23 -0
  4. package/server/http/middleware.js +58 -2
  5. package/server/http/routes.js +2 -5
  6. package/server/index.js +13 -0
  7. package/server/public/.last_build_id +1 -1
  8. package/server/public/assets/NOTICES +2534 -1951
  9. package/server/public/assets/fonts/MaterialIcons-Regular.otf +0 -0
  10. package/server/public/canvaskit/canvaskit.js.symbols +99 -99
  11. package/server/public/canvaskit/canvaskit.wasm +0 -0
  12. package/server/public/canvaskit/chromium/canvaskit.js.symbols +57 -57
  13. package/server/public/canvaskit/chromium/canvaskit.wasm +0 -0
  14. package/server/public/canvaskit/skwasm.js.symbols +3 -3
  15. package/server/public/canvaskit/skwasm.wasm +0 -0
  16. package/server/public/canvaskit/skwasm_heavy.js.symbols +3 -3
  17. package/server/public/canvaskit/skwasm_heavy.wasm +0 -0
  18. package/server/public/canvaskit/wimp.js.symbols +951 -951
  19. package/server/public/canvaskit/wimp.wasm +0 -0
  20. package/server/public/flutter_bootstrap.js +2 -2
  21. package/server/public/main.dart.js +73210 -66073
  22. package/server/routes/agents.js +46 -3
  23. package/server/routes/android.js +52 -138
  24. package/server/routes/browser.js +30 -13
  25. package/server/routes/memory.js +13 -16
  26. package/server/routes/recordings.js +171 -42
  27. package/server/routes/settings.js +21 -13
  28. package/server/routes/wearables.js +169 -0
  29. package/server/services/ai/capabilityHealth.js +253 -0
  30. package/server/services/ai/compaction.js +16 -5
  31. package/server/services/ai/engine.js +1104 -31
  32. package/server/services/ai/history.js +4 -4
  33. package/server/services/ai/models.js +90 -1
  34. package/server/services/ai/multiStep.js +12 -6
  35. package/server/services/ai/providers/grok.js +36 -6
  36. package/server/services/ai/recordingInsights.js +77 -0
  37. package/server/services/ai/settings.js +14 -4
  38. package/server/services/ai/systemPrompt.js +78 -11
  39. package/server/services/ai/taskAnalysis.js +317 -0
  40. package/server/services/ai/toolResult.js +23 -11
  41. package/server/services/ai/tools.js +407 -37
  42. package/server/services/android/controller.js +290 -50
  43. package/server/services/browser/controller.js +1 -1
  44. package/server/services/commands/router.js +350 -0
  45. package/server/services/manager.js +188 -0
  46. package/server/services/memory/manager.js +208 -61
  47. package/server/services/messaging/automation.js +69 -1
  48. package/server/services/messaging/telegram.js +40 -19
  49. package/server/services/recordings/manager.js +259 -33
  50. package/server/services/scheduler/cron.js +206 -82
  51. package/server/services/wearables/manager.js +541 -0
  52. package/server/services/wearables/protocols/base.js +61 -0
  53. package/server/services/wearables/protocols/heypocket.js +108 -0
  54. package/server/services/websocket.js +46 -44
@@ -44,7 +44,7 @@ Telegram, Discord, and WhatsApp tokens are stored in the database via the Flutte
44
44
 
45
45
  - Config: `~/.neoagent/.env`
46
46
  - Database/session/logs: `~/.neoagent/data/`
47
- - Skills/soul/daily memory files: `~/.neoagent/agent-data/`
47
+ - Skills/memory/daily data files: `~/.neoagent/agent-data/`
48
48
 
49
49
  ---
50
50
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "neoagent",
3
- "version": "2.1.17-beta.2",
3
+ "version": "2.1.17-beta.21",
4
4
  "description": "Proactive personal AI agent with no limits",
5
5
  "license": "MIT",
6
6
  "main": "server/index.js",
@@ -46,9 +46,9 @@
46
46
  "@google/generative-ai": "^0.24.0",
47
47
  "@modelcontextprotocol/sdk": "^1.12.1",
48
48
  "baileys": "^6.7.1",
49
- "bcrypt": "^5.1.1",
49
+ "bcrypt": "^6.0.0",
50
50
  "better-sqlite3": "^11.8.1",
51
- "connect-sqlite3": "^0.9.15",
51
+ "better-sqlite3-session-store": "^0.1.0",
52
52
  "cors": "^2.8.5",
53
53
  "discord.js": "^14.25.1",
54
54
  "dotenv": "^16.4.7",
@@ -59,13 +59,17 @@
59
59
  "multer": "^1.4.5-lts.1",
60
60
  "node-cron": "^3.0.3",
61
61
  "node-pty": "^1.0.0",
62
- "node-telegram-bot-api": "^0.67.0",
63
62
  "openai": "^4.85.4",
63
+ "proper-lockfile": "^4.1.2",
64
64
  "puppeteer-core": "^24.40.0",
65
65
  "puppeteer-extra": "^3.3.6",
66
66
  "puppeteer-extra-plugin-stealth": "^2.11.2",
67
67
  "socket.io": "^4.8.1",
68
+ "telegraf": "^4.16.3",
68
69
  "telnyx": "^5.51.0",
69
70
  "uuid": "^11.1.0"
71
+ },
72
+ "overrides": {
73
+ "undici": "^6.24.0"
70
74
  }
71
75
  }
@@ -39,6 +39,7 @@ db.exec(`
39
39
  model TEXT,
40
40
  total_tokens INTEGER DEFAULT 0,
41
41
  prompt_metrics TEXT,
42
+ metadata_json TEXT,
42
43
  error TEXT,
43
44
  final_response TEXT,
44
45
  created_at TEXT DEFAULT (datetime('now')),
@@ -146,6 +147,8 @@ db.exec(`
146
147
  compaction_count INTEGER DEFAULT 0,
147
148
  summary TEXT,
148
149
  summary_message_count INTEGER DEFAULT 0,
150
+ working_state_json TEXT,
151
+ last_verified_facts_json TEXT,
149
152
  last_compaction TEXT,
150
153
  last_summary TEXT,
151
154
  created_at TEXT DEFAULT (datetime('now')),
@@ -267,6 +270,7 @@ db.exec(`
267
270
  transcript_text TEXT,
268
271
  transcript_language TEXT,
269
272
  transcript_model TEXT,
273
+ structured_content_json TEXT,
270
274
  started_at TEXT DEFAULT (datetime('now')),
271
275
  ended_at TEXT,
272
276
  duration_ms INTEGER DEFAULT 0,
@@ -277,6 +281,21 @@ db.exec(`
277
281
  FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
278
282
  );
279
283
 
284
+ CREATE TABLE IF NOT EXISTS wearable_devices (
285
+ id TEXT PRIMARY KEY,
286
+ user_id INTEGER NOT NULL,
287
+ mac_address TEXT,
288
+ protocol TEXT NOT NULL,
289
+ name TEXT NOT NULL,
290
+ status TEXT DEFAULT 'disconnected',
291
+ battery_level INTEGER,
292
+ last_seen_at TEXT,
293
+ created_at TEXT DEFAULT (datetime('now')),
294
+ updated_at TEXT DEFAULT (datetime('now')),
295
+ FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
296
+ UNIQUE(user_id, mac_address)
297
+ );
298
+
280
299
  CREATE TABLE IF NOT EXISTS recording_sources (
281
300
  id TEXT PRIMARY KEY,
282
301
  session_id TEXT NOT NULL,
@@ -390,13 +409,17 @@ for (const col of [
390
409
  "ALTER TABLE scheduled_tasks ADD COLUMN run_at TEXT",
391
410
  "ALTER TABLE scheduled_tasks ADD COLUMN one_time INTEGER DEFAULT 0",
392
411
  "ALTER TABLE agent_runs ADD COLUMN prompt_metrics TEXT",
412
+ "ALTER TABLE agent_runs ADD COLUMN metadata_json TEXT",
393
413
  "ALTER TABLE agent_runs ADD COLUMN final_response TEXT",
394
414
  "ALTER TABLE conversations ADD COLUMN summary TEXT",
395
415
  "ALTER TABLE conversations ADD COLUMN summary_message_count INTEGER DEFAULT 0",
416
+ "ALTER TABLE conversations ADD COLUMN working_state_json TEXT",
417
+ "ALTER TABLE conversations ADD COLUMN last_verified_facts_json TEXT",
396
418
  "ALTER TABLE conversations ADD COLUMN last_summary TEXT",
397
419
  "ALTER TABLE recording_sessions ADD COLUMN transcript_language TEXT",
398
420
  "ALTER TABLE recording_sessions ADD COLUMN transcript_model TEXT",
399
421
  "ALTER TABLE recording_sessions ADD COLUMN duration_ms INTEGER DEFAULT 0",
422
+ "ALTER TABLE recording_sessions ADD COLUMN structured_content_json TEXT",
400
423
  ]) {
401
424
  try { db.exec(col); } catch { /* column already exists */ }
402
425
  }
@@ -1,12 +1,62 @@
1
1
  'use strict';
2
2
 
3
3
  const session = require('express-session');
4
- const SQLiteStore = require('connect-sqlite3')(session);
4
+ const Sqlite = require('better-sqlite3');
5
+ const SQLiteStore = require('better-sqlite3-session-store')(session);
5
6
  const helmet = require('helmet');
6
7
  const cors = require('cors');
7
8
  const { DATA_DIR } = require('../../runtime/paths');
8
9
  const { logRequestSummary } = require('../utils/logger');
9
10
 
11
+ const sessionsDb = new Sqlite(`${DATA_DIR}/sessions.db`);
12
+
13
+ function ensureSessionStoreSchema(db) {
14
+ const table = db.prepare("SELECT name FROM sqlite_master WHERE type = 'table' AND name = 'sessions'").get();
15
+ if (!table) {
16
+ db.exec('CREATE TABLE sessions (sid PRIMARY KEY, sess, expire)');
17
+ return;
18
+ }
19
+
20
+ const columns = db.prepare('PRAGMA table_info(sessions)').all().map((row) => row.name);
21
+ const expected = ['sid', 'sess', 'expire'];
22
+ if (columns.length === expected.length && columns.every((name, index) => name === expected[index])) {
23
+ return;
24
+ }
25
+
26
+ const hasSid = columns.includes('sid');
27
+ const hasSess = columns.includes('sess');
28
+ const expireColumn = columns.includes('expire') ? 'expire' : (columns.includes('expired') ? 'expired' : null);
29
+
30
+ const legacyTableName = `sessions_legacy_${Date.now()}`;
31
+ db.exec('BEGIN');
32
+ try {
33
+ db.exec(`ALTER TABLE sessions RENAME TO ${legacyTableName}`);
34
+ db.exec('CREATE TABLE sessions (sid PRIMARY KEY, sess, expire)');
35
+
36
+ if (hasSid && hasSess) {
37
+ // TODO: Verify whether better-sqlite3-session-store treats expire=0 as already expired or non-expiring.
38
+ const expireExpr = expireColumn ? expireColumn : 'NULL';
39
+ db.exec(`
40
+ INSERT OR REPLACE INTO sessions (sid, sess, expire)
41
+ SELECT sid, sess, COALESCE(${expireExpr}, 0) AS expire
42
+ FROM ${legacyTableName}
43
+ WHERE sid IS NOT NULL
44
+ `);
45
+ }
46
+
47
+ db.exec(`DROP TABLE ${legacyTableName}`);
48
+ db.exec('COMMIT');
49
+ console.warn('[Session] Normalized sessions table schema to (sid, sess, expire).');
50
+ } catch (error) {
51
+ try {
52
+ db.exec('ROLLBACK');
53
+ } catch {}
54
+ throw error;
55
+ }
56
+ }
57
+
58
+ ensureSessionStoreSchema(sessionsDb);
59
+
10
60
  function buildHelmetOptions({ secureCookies }) {
11
61
  const wsConnectSrc = secureCookies ? ['wss:'] : ['ws:', 'wss:'];
12
62
 
@@ -48,7 +98,13 @@ function buildHelmetOptions({ secureCookies }) {
48
98
 
49
99
  function createSessionMiddleware({ secureCookies }) {
50
100
  return session({
51
- store: new SQLiteStore({ db: 'sessions.db', dir: DATA_DIR }),
101
+ store: new SQLiteStore({
102
+ client: sessionsDb,
103
+ expired: {
104
+ clear: true,
105
+ intervalMs: 15 * 60 * 1000,
106
+ },
107
+ }),
52
108
  secret: process.env.SESSION_SECRET || 'neoagent-dev-secret-change-me',
53
109
  name: 'neoagent.sid',
54
110
  resave: false,
@@ -17,6 +17,7 @@ const routeRegistry = [
17
17
  { basePath: '/api/browser', modulePath: '../routes/browser' },
18
18
  { basePath: '/api/android', modulePath: '../routes/android' },
19
19
  { basePath: '/api/recordings', modulePath: '../routes/recordings' },
20
+ { basePath: '/api/wearables', modulePath: '../routes/wearables' },
20
21
  { basePath: '/api/mobile/health', modulePath: '../routes/mobile-health' }
21
22
  ];
22
23
 
@@ -25,25 +26,21 @@ function registerApiRoutes(app) {
25
26
  const handler = require(route.modulePath);
26
27
  if (route.basePath) {
27
28
  app.use(route.basePath, handler);
28
- console.log(`[HTTP] Registered API route ${route.basePath} -> ${route.modulePath}`);
29
29
  } else {
30
30
  app.use(handler);
31
- console.log(`[HTTP] Registered API route ${route.modulePath}`);
32
31
  }
33
32
  }
34
33
 
35
34
  setupTelnyxWebhook(app);
36
- console.log('[HTTP] Registered Telnyx webhook');
37
35
 
38
36
  app.get('/api/health', requireAuth, (req, res) => {
39
37
  res.json({ status: 'ok', timestamp: new Date().toISOString() });
40
38
  });
41
- console.log('[HTTP] Registered API route /api/health');
42
39
 
43
40
  app.get('/api/version', requireAuth, (req, res) => {
44
41
  res.json(getVersionInfo());
45
42
  });
46
- console.log('[HTTP] Registered API route /api/version');
43
+ console.log(`[HTTP] Registered ${routeRegistry.length + 3} routes`);
47
44
  }
48
45
 
49
46
  module.exports = {
package/server/index.js CHANGED
@@ -29,6 +29,19 @@ const { startServices, stopServices } = require('./services/manager');
29
29
  const PORT = Number(process.env.PORT) || 3333;
30
30
  const SECURE_COOKIES = process.env.SECURE_COOKIES === 'true';
31
31
 
32
+ function logStartupConfig() {
33
+ const flags = {
34
+ SESSION_SECRET: Boolean(process.env.SESSION_SECRET),
35
+ OPENAI_API_KEY: Boolean(process.env.OPENAI_API_KEY),
36
+ DEEPGRAM_API_KEY: Boolean(process.env.DEEPGRAM_API_KEY),
37
+ };
38
+
39
+ console.log(`[Startup] Using env file: ${ENV_FILE}`);
40
+ console.log('[Startup] Key availability:', flags);
41
+ }
42
+
43
+ logStartupConfig();
44
+
32
45
  if (!process.env.SESSION_SECRET) {
33
46
  console.warn(
34
47
  'WARNING: SESSION_SECRET not set — using insecure default. Set it in .env before exposing this server.'
@@ -1 +1 @@
1
- e38b9444952230adccfb989891baa8ec
1
+ 1364c60312b13e5d80c77b1708e33bfb