neoagent 2.3.1-beta.2 → 2.3.1-beta.3
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/README.md +2 -0
- package/package.json +2 -1
- package/server/db/database.js +57 -0
- package/server/http/routes/screenHistory.js +46 -0
- package/server/http/routes/triggers.js +81 -0
- package/server/http/routes.js +3 -1
- package/server/public/assets/NOTICES +61 -0
- package/server/public/assets/fonts/MaterialIcons-Regular.otf +0 -0
- package/server/public/flutter_bootstrap.js +1 -1
- package/server/public/main.dart.js +42896 -42725
- package/server/services/ai/systemPrompt.js +1 -1
- package/server/services/ai/tools.js +35 -6
- package/server/services/browser/controller.js +47 -3
- package/server/services/desktop/screenRecorder.js +126 -0
- package/server/services/integrations/whatsapp/provider.js +6 -2
- package/server/services/manager.js +22 -0
- package/server/services/skills/base_catalog.js +33 -0
- package/server/services/tasks/adapters/index.js +1 -0
- package/server/services/tasks/adapters/manual.js +12 -0
- package/server/services/tasks/runtime.js +1 -1
- package/server/services/widgets/service.js +49 -4
package/README.md
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "neoagent",
|
|
3
|
-
"version": "2.3.1-beta.
|
|
3
|
+
"version": "2.3.1-beta.3",
|
|
4
4
|
"description": "Proactive personal AI agent with no limits",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"main": "server/index.js",
|
|
@@ -80,6 +80,7 @@
|
|
|
80
80
|
"socket.io": "^4.8.1",
|
|
81
81
|
"telegraf": "^4.16.3",
|
|
82
82
|
"telnyx": "^5.51.0",
|
|
83
|
+
"tesseract.js": "^7.0.0",
|
|
83
84
|
"uuid": "^11.1.0",
|
|
84
85
|
"ws": "^8.19.0"
|
|
85
86
|
},
|
package/server/db/database.js
CHANGED
|
@@ -651,6 +651,40 @@ db.exec(`
|
|
|
651
651
|
CREATE INDEX IF NOT EXISTS idx_recording_chunks_source ON recording_chunks(source_id, sequence_index);
|
|
652
652
|
CREATE INDEX IF NOT EXISTS idx_recording_segments_session ON recording_transcript_segments(session_id, start_ms, created_at);
|
|
653
653
|
|
|
654
|
+
CREATE TABLE IF NOT EXISTS screen_history (
|
|
655
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
656
|
+
user_id INTEGER NOT NULL,
|
|
657
|
+
timestamp TEXT DEFAULT (datetime('now')),
|
|
658
|
+
app_name TEXT,
|
|
659
|
+
text_content TEXT,
|
|
660
|
+
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
|
|
661
|
+
);
|
|
662
|
+
|
|
663
|
+
CREATE TABLE IF NOT EXISTS notification_history (
|
|
664
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
665
|
+
user_id INTEGER NOT NULL,
|
|
666
|
+
app_package TEXT,
|
|
667
|
+
title TEXT,
|
|
668
|
+
body TEXT,
|
|
669
|
+
timestamp TEXT DEFAULT (datetime('now')),
|
|
670
|
+
action_taken TEXT,
|
|
671
|
+
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
|
|
672
|
+
);
|
|
673
|
+
|
|
674
|
+
CREATE TABLE IF NOT EXISTS geofences (
|
|
675
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
676
|
+
user_id INTEGER NOT NULL,
|
|
677
|
+
label TEXT,
|
|
678
|
+
latitude REAL NOT NULL,
|
|
679
|
+
longitude REAL NOT NULL,
|
|
680
|
+
radius_meters INTEGER NOT NULL,
|
|
681
|
+
trigger_action TEXT,
|
|
682
|
+
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
|
|
683
|
+
);
|
|
684
|
+
|
|
685
|
+
CREATE INDEX IF NOT EXISTS idx_screen_history_user ON screen_history(user_id, timestamp DESC);
|
|
686
|
+
CREATE INDEX IF NOT EXISTS idx_notification_history_user ON notification_history(user_id, timestamp DESC);
|
|
687
|
+
|
|
654
688
|
CREATE TABLE IF NOT EXISTS artifacts (
|
|
655
689
|
id TEXT PRIMARY KEY,
|
|
656
690
|
user_id INTEGER NOT NULL,
|
|
@@ -676,6 +710,29 @@ db.exec(`
|
|
|
676
710
|
|
|
677
711
|
try {
|
|
678
712
|
db.exec(`
|
|
713
|
+
CREATE VIRTUAL TABLE IF NOT EXISTS screen_history_fts USING fts5(
|
|
714
|
+
text_content,
|
|
715
|
+
app_name,
|
|
716
|
+
timestamp UNINDEXED,
|
|
717
|
+
user_id UNINDEXED,
|
|
718
|
+
tokenize = 'porter unicode61'
|
|
719
|
+
);
|
|
720
|
+
|
|
721
|
+
CREATE TRIGGER IF NOT EXISTS screen_history_fts_ai AFTER INSERT ON screen_history BEGIN
|
|
722
|
+
INSERT INTO screen_history_fts(rowid, text_content, app_name, timestamp, user_id)
|
|
723
|
+
VALUES (new.id, COALESCE(new.text_content, ''), COALESCE(new.app_name, ''), new.timestamp, new.user_id);
|
|
724
|
+
END;
|
|
725
|
+
|
|
726
|
+
CREATE TRIGGER IF NOT EXISTS screen_history_fts_ad AFTER DELETE ON screen_history BEGIN
|
|
727
|
+
DELETE FROM screen_history_fts WHERE rowid = old.id;
|
|
728
|
+
END;
|
|
729
|
+
|
|
730
|
+
CREATE TRIGGER IF NOT EXISTS screen_history_fts_au AFTER UPDATE ON screen_history BEGIN
|
|
731
|
+
DELETE FROM screen_history_fts WHERE rowid = old.id;
|
|
732
|
+
INSERT INTO screen_history_fts(rowid, text_content, app_name, timestamp, user_id)
|
|
733
|
+
VALUES (new.id, COALESCE(new.text_content, ''), COALESCE(new.app_name, ''), new.timestamp, new.user_id);
|
|
734
|
+
END;
|
|
735
|
+
|
|
679
736
|
CREATE VIRTUAL TABLE IF NOT EXISTS conversation_history_fts USING fts5(
|
|
680
737
|
content,
|
|
681
738
|
role UNINDEXED,
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const express = require('express');
|
|
4
|
+
const db = require('../../db/database');
|
|
5
|
+
const { getErrorMessage } = require('../bootstrap_helpers');
|
|
6
|
+
|
|
7
|
+
const router = express.Router();
|
|
8
|
+
|
|
9
|
+
router.get('/search', (req, res) => {
|
|
10
|
+
const { q, limit = 50, offset = 0 } = req.query;
|
|
11
|
+
|
|
12
|
+
if (!req.user || !req.user.id) {
|
|
13
|
+
return res.status(401).json({ error: 'Unauthorized' });
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
try {
|
|
17
|
+
let results = [];
|
|
18
|
+
if (q) {
|
|
19
|
+
// Full text search
|
|
20
|
+
results = db.prepare(\`
|
|
21
|
+
SELECT s.id, s.timestamp, s.app_name, s.text_content
|
|
22
|
+
FROM screen_history_fts fts
|
|
23
|
+
JOIN screen_history s ON fts.rowid = s.id
|
|
24
|
+
WHERE screen_history_fts MATCH ? AND s.user_id = ?
|
|
25
|
+
ORDER BY s.timestamp DESC
|
|
26
|
+
LIMIT ? OFFSET ?
|
|
27
|
+
\`).all(q, req.user.id, Number(limit), Number(offset));
|
|
28
|
+
} else {
|
|
29
|
+
// Recent history
|
|
30
|
+
results = db.prepare(\`
|
|
31
|
+
SELECT id, timestamp, app_name, text_content
|
|
32
|
+
FROM screen_history
|
|
33
|
+
WHERE user_id = ?
|
|
34
|
+
ORDER BY timestamp DESC
|
|
35
|
+
LIMIT ? OFFSET ?
|
|
36
|
+
\`).all(req.user.id, Number(limit), Number(offset));
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
res.json({ results });
|
|
40
|
+
} catch (err) {
|
|
41
|
+
console.error('[ScreenHistory] Search error:', getErrorMessage(err));
|
|
42
|
+
res.status(500).json({ error: 'Failed to search screen history' });
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
module.exports = router;
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const express = require('express');
|
|
4
|
+
const db = require('../../db/database');
|
|
5
|
+
const { getErrorMessage } = require('../bootstrap_helpers');
|
|
6
|
+
const { requireAuth } = require('../middleware/auth');
|
|
7
|
+
|
|
8
|
+
const router = express.Router();
|
|
9
|
+
|
|
10
|
+
router.use(requireAuth);
|
|
11
|
+
|
|
12
|
+
router.post('/geofence', async (req, res) => {
|
|
13
|
+
const { label, latitude, longitude, radius_meters, action } = req.body;
|
|
14
|
+
|
|
15
|
+
try {
|
|
16
|
+
const userRow = db.prepare('SELECT id FROM users WHERE id = ?').get(req.user.id);
|
|
17
|
+
if (!userRow) return res.status(401).json({ error: 'Unauthorized' });
|
|
18
|
+
|
|
19
|
+
console.log(`[Triggers] Geofence entered: ${label} by user ${req.user.id}`);
|
|
20
|
+
|
|
21
|
+
// If an agentEngine is running, we can inject a prompt to process this context
|
|
22
|
+
const agentEngine = req.app.locals.agentEngine;
|
|
23
|
+
if (agentEngine) {
|
|
24
|
+
// Find active agent or use default
|
|
25
|
+
const defaultAgentId = db.prepare('SELECT id FROM agents WHERE user_id = ? ORDER BY is_default DESC LIMIT 1').get(req.user.id)?.id;
|
|
26
|
+
|
|
27
|
+
if (defaultAgentId) {
|
|
28
|
+
// Fire and forget a trigger message to the agent
|
|
29
|
+
agentEngine.handleBackgroundTrigger(req.user.id, defaultAgentId, {
|
|
30
|
+
source: 'geofence',
|
|
31
|
+
label,
|
|
32
|
+
action: action || 'User entered a geofenced area. Check if there are any active reminders or tasks related to this location.'
|
|
33
|
+
}).catch(err => console.error('[Triggers] Agent evaluation failed:', err));
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
res.json({ success: true, message: 'Geofence trigger processed' });
|
|
38
|
+
} catch (err) {
|
|
39
|
+
console.error('[Triggers] Geofence error:', getErrorMessage(err));
|
|
40
|
+
res.status(500).json({ error: 'Failed to process geofence trigger' });
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
router.post('/notification', async (req, res) => {
|
|
45
|
+
const { app_package, title, body, action_taken } = req.body;
|
|
46
|
+
|
|
47
|
+
try {
|
|
48
|
+
const userRow = db.prepare('SELECT id FROM users WHERE id = ?').get(req.user.id);
|
|
49
|
+
if (!userRow) return res.status(401).json({ error: 'Unauthorized' });
|
|
50
|
+
|
|
51
|
+
console.log(`[Triggers] Notification received: ${app_package} - ${title}`);
|
|
52
|
+
|
|
53
|
+
db.prepare(\`
|
|
54
|
+
INSERT INTO notification_history (user_id, app_package, title, body, action_taken)
|
|
55
|
+
VALUES (?, ?, ?, ?, ?)
|
|
56
|
+
\`).run(req.user.id, app_package || 'unknown', title || '', body || '', action_taken || 'none');
|
|
57
|
+
|
|
58
|
+
// Notify agent engine to proactively evaluate the notification
|
|
59
|
+
const agentEngine = req.app.locals.agentEngine;
|
|
60
|
+
if (agentEngine) {
|
|
61
|
+
const defaultAgentId = db.prepare('SELECT id FROM agents WHERE user_id = ? ORDER BY is_default DESC LIMIT 1').get(req.user.id)?.id;
|
|
62
|
+
|
|
63
|
+
if (defaultAgentId) {
|
|
64
|
+
agentEngine.handleBackgroundTrigger(req.user.id, defaultAgentId, {
|
|
65
|
+
source: 'notification',
|
|
66
|
+
app_package,
|
|
67
|
+
title,
|
|
68
|
+
body,
|
|
69
|
+
instruction: 'Evaluate this notification. If it is an important reminder, calendar event, or urgent message, inform the user or take appropriate action.'
|
|
70
|
+
}).catch(err => console.error('[Triggers] Agent evaluation failed:', err));
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
res.json({ success: true, message: 'Notification trigger processed and stored' });
|
|
75
|
+
} catch (err) {
|
|
76
|
+
console.error('[Triggers] Notification error:', getErrorMessage(err));
|
|
77
|
+
res.status(500).json({ error: 'Failed to process notification trigger' });
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
module.exports = router;
|
package/server/http/routes.js
CHANGED
|
@@ -26,7 +26,9 @@ const routeRegistry = [
|
|
|
26
26
|
{ basePath: '/api/desktop', modulePath: '../routes/desktop' },
|
|
27
27
|
{ basePath: '/api/recordings', modulePath: '../routes/recordings' },
|
|
28
28
|
{ basePath: '/api/voice-assistant', modulePath: '../routes/voice_assistant' },
|
|
29
|
-
{ basePath: '/api/mobile/health', modulePath: '../routes/mobile-health' }
|
|
29
|
+
{ basePath: '/api/mobile/health', modulePath: '../routes/mobile-health' },
|
|
30
|
+
{ basePath: '/api/screen-history', modulePath: '../routes/screenHistory' },
|
|
31
|
+
{ basePath: '/api/triggers', modulePath: '../routes/triggers' }
|
|
30
32
|
];
|
|
31
33
|
|
|
32
34
|
function registerApiRoutes(app) {
|
|
@@ -5535,6 +5535,19 @@ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
|
5535
5535
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
5536
5536
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
5537
5537
|
--------------------------------------------------------------------------------
|
|
5538
|
+
flutter_background_service
|
|
5539
|
+
flutter_background_service_android
|
|
5540
|
+
flutter_background_service_ios
|
|
5541
|
+
flutter_background_service_platform_interface
|
|
5542
|
+
|
|
5543
|
+
Copyright 2022 Eka Setiawan Saputra
|
|
5544
|
+
|
|
5545
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
5546
|
+
|
|
5547
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
5548
|
+
|
|
5549
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
5550
|
+
--------------------------------------------------------------------------------
|
|
5538
5551
|
flutter_lints
|
|
5539
5552
|
flutter_markdown
|
|
5540
5553
|
path_provider
|
|
@@ -7093,6 +7106,35 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
|
7093
7106
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
7094
7107
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
7095
7108
|
--------------------------------------------------------------------------------
|
|
7109
|
+
geolocator
|
|
7110
|
+
geolocator_android
|
|
7111
|
+
geolocator_apple
|
|
7112
|
+
geolocator_platform_interface
|
|
7113
|
+
geolocator_web
|
|
7114
|
+
geolocator_windows
|
|
7115
|
+
|
|
7116
|
+
MIT License
|
|
7117
|
+
|
|
7118
|
+
Copyright (c) 2018 Baseflow
|
|
7119
|
+
|
|
7120
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
7121
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7122
|
+
in the Software without restriction, including without limitation the rights
|
|
7123
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
7124
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
7125
|
+
furnished to do so, subject to the following conditions:
|
|
7126
|
+
|
|
7127
|
+
The above copyright notice and this permission notice shall be included in all
|
|
7128
|
+
copies or substantial portions of the Software.
|
|
7129
|
+
|
|
7130
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
7131
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
7132
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
7133
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
7134
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
7135
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
7136
|
+
SOFTWARE.
|
|
7137
|
+
--------------------------------------------------------------------------------
|
|
7096
7138
|
glfw
|
|
7097
7139
|
|
|
7098
7140
|
|
|
@@ -24797,6 +24839,25 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
|
24797
24839
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
24798
24840
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
24799
24841
|
--------------------------------------------------------------------------------
|
|
24842
|
+
notification_listener_service
|
|
24843
|
+
|
|
24844
|
+
Copyright (c) 2022 Iheb Briki
|
|
24845
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
24846
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
24847
|
+
in the Software without restriction, including without limitation the rights
|
|
24848
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
24849
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
24850
|
+
furnished to do so, subject to the following conditions:
|
|
24851
|
+
The above copyright notice and this permission notice shall be included in all
|
|
24852
|
+
copies or substantial portions of the Software.
|
|
24853
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
24854
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
24855
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
24856
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
24857
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
24858
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
24859
|
+
SOFTWARE.
|
|
24860
|
+
--------------------------------------------------------------------------------
|
|
24800
24861
|
perfetto
|
|
24801
24862
|
|
|
24802
24863
|
Apache License
|
|
Binary file
|
|
@@ -37,6 +37,6 @@ _flutter.buildConfig = {"engineRevision":"59aa584fdf100e6c78c785d8a5b565d1de4b48
|
|
|
37
37
|
|
|
38
38
|
_flutter.loader.load({
|
|
39
39
|
serviceWorkerSettings: {
|
|
40
|
-
serviceWorkerVersion: "
|
|
40
|
+
serviceWorkerVersion: "1375002290" /* Flutter's service worker is deprecated and will be removed in a future Flutter release. */
|
|
41
41
|
}
|
|
42
42
|
});
|