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.
- package/docs/configuration.md +1 -1
- package/package.json +8 -4
- package/server/db/database.js +23 -0
- package/server/http/middleware.js +58 -2
- package/server/http/routes.js +2 -5
- package/server/index.js +13 -0
- package/server/public/.last_build_id +1 -1
- package/server/public/assets/NOTICES +2534 -1951
- package/server/public/assets/fonts/MaterialIcons-Regular.otf +0 -0
- package/server/public/canvaskit/canvaskit.js.symbols +99 -99
- package/server/public/canvaskit/canvaskit.wasm +0 -0
- package/server/public/canvaskit/chromium/canvaskit.js.symbols +57 -57
- package/server/public/canvaskit/chromium/canvaskit.wasm +0 -0
- package/server/public/canvaskit/skwasm.js.symbols +3 -3
- package/server/public/canvaskit/skwasm.wasm +0 -0
- package/server/public/canvaskit/skwasm_heavy.js.symbols +3 -3
- package/server/public/canvaskit/skwasm_heavy.wasm +0 -0
- package/server/public/canvaskit/wimp.js.symbols +951 -951
- package/server/public/canvaskit/wimp.wasm +0 -0
- package/server/public/flutter_bootstrap.js +2 -2
- package/server/public/main.dart.js +73210 -66073
- package/server/routes/agents.js +46 -3
- package/server/routes/android.js +52 -138
- package/server/routes/browser.js +30 -13
- package/server/routes/memory.js +13 -16
- package/server/routes/recordings.js +171 -42
- package/server/routes/settings.js +21 -13
- package/server/routes/wearables.js +169 -0
- package/server/services/ai/capabilityHealth.js +253 -0
- package/server/services/ai/compaction.js +16 -5
- package/server/services/ai/engine.js +1104 -31
- package/server/services/ai/history.js +4 -4
- package/server/services/ai/models.js +90 -1
- package/server/services/ai/multiStep.js +12 -6
- package/server/services/ai/providers/grok.js +36 -6
- package/server/services/ai/recordingInsights.js +77 -0
- package/server/services/ai/settings.js +14 -4
- package/server/services/ai/systemPrompt.js +78 -11
- package/server/services/ai/taskAnalysis.js +317 -0
- package/server/services/ai/toolResult.js +23 -11
- package/server/services/ai/tools.js +407 -37
- package/server/services/android/controller.js +290 -50
- package/server/services/browser/controller.js +1 -1
- package/server/services/commands/router.js +350 -0
- package/server/services/manager.js +188 -0
- package/server/services/memory/manager.js +208 -61
- package/server/services/messaging/automation.js +69 -1
- package/server/services/messaging/telegram.js +40 -19
- package/server/services/recordings/manager.js +259 -33
- package/server/services/scheduler/cron.js +206 -82
- package/server/services/wearables/manager.js +541 -0
- package/server/services/wearables/protocols/base.js +61 -0
- package/server/services/wearables/protocols/heypocket.js +108 -0
- package/server/services/websocket.js +46 -44
package/docs/configuration.md
CHANGED
|
@@ -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/
|
|
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.
|
|
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": "^
|
|
49
|
+
"bcrypt": "^6.0.0",
|
|
50
50
|
"better-sqlite3": "^11.8.1",
|
|
51
|
-
"
|
|
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
|
}
|
package/server/db/database.js
CHANGED
|
@@ -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
|
|
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({
|
|
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,
|
package/server/http/routes.js
CHANGED
|
@@ -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(
|
|
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
|
-
|
|
1
|
+
1364c60312b13e5d80c77b1708e33bfb
|