neoagent 2.4.4-beta.0 → 2.4.4-beta.5
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 +5 -3
- package/docs/capabilities.md +16 -7
- package/docs/index.md +1 -0
- package/docs/security-boundaries.md +122 -0
- package/docs/supermemory-memory-review.md +852 -0
- package/flutter_app/lib/features/memory/views/retrieval_inspector_view.dart +128 -0
- package/flutter_app/lib/main.dart +3 -0
- package/flutter_app/lib/main_app_shell.dart +22 -0
- package/flutter_app/lib/main_controller.dart +36 -1
- package/flutter_app/lib/main_operations.dart +13 -0
- package/flutter_app/lib/main_security.dart +971 -0
- package/flutter_app/lib/main_settings.dart +61 -0
- package/flutter_app/lib/src/backend_client.dart +60 -3
- package/flutter_app/macos/Flutter/GeneratedPluginRegistrant.swift +2 -0
- package/flutter_app/pubspec.lock +32 -0
- package/flutter_app/pubspec.yaml +1 -0
- package/lib/schema_migrations.js +237 -0
- package/package.json +4 -2
- package/server/db/database.js +3 -0
- package/server/http/routes.js +2 -1
- package/server/public/.last_build_id +1 -1
- package/server/public/assets/NOTICES +86 -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 +80911 -79117
- package/server/routes/memory.js +39 -2
- package/server/routes/security.js +112 -0
- package/server/services/ai/engine.js +267 -10
- package/server/services/ai/systemPrompt.js +13 -2
- package/server/services/cli/shell_worker.js +135 -0
- package/server/services/cli/shell_worker_pool.js +125 -0
- package/server/services/manager.js +20 -1
- package/server/services/memory/consolidation.js +111 -0
- package/server/services/memory/embedding_index.js +175 -0
- package/server/services/memory/embeddings.js +22 -2
- package/server/services/memory/evaluation.js +187 -0
- package/server/services/memory/ingestion_chunking.js +191 -0
- package/server/services/memory/ingestion_documents.js +96 -26
- package/server/services/memory/intelligence.js +3 -1
- package/server/services/memory/manager.js +855 -40
- package/server/services/memory/policy.js +0 -40
- package/server/services/memory/retrieval_reasoning.js +191 -0
- package/server/services/runtime/manager.js +7 -0
- package/server/services/security/approval_gate_service.js +93 -0
- package/server/services/security/tool_categories.js +105 -0
- package/server/services/security/tool_policy_service.js +92 -0
- package/server/services/security/tool_security_hook.js +77 -0
|
@@ -148,12 +148,24 @@ const _diagnosticsSettingsSection = _SettingsSection('diagnostics', <String>[
|
|
|
148
148
|
'health',
|
|
149
149
|
]);
|
|
150
150
|
|
|
151
|
+
const _securitySettingsSection = _SettingsSection('security', <String>[
|
|
152
|
+
'security',
|
|
153
|
+
'tool',
|
|
154
|
+
'permission',
|
|
155
|
+
'allowlist',
|
|
156
|
+
'shell',
|
|
157
|
+
'android',
|
|
158
|
+
'approval',
|
|
159
|
+
'policy',
|
|
160
|
+
]);
|
|
161
|
+
|
|
151
162
|
const List<_SettingsSection> _settingsSearchSections = <_SettingsSection>[
|
|
152
163
|
_overviewSettingsSection,
|
|
153
164
|
_workspaceSettingsSection,
|
|
154
165
|
_modelsSettingsSection,
|
|
155
166
|
_voiceRecordingSettingsSection,
|
|
156
167
|
_desktopSettingsSection,
|
|
168
|
+
_securitySettingsSection,
|
|
157
169
|
_diagnosticsSettingsSection,
|
|
158
170
|
];
|
|
159
171
|
|
|
@@ -399,6 +411,13 @@ class _SettingsPanelState extends State<SettingsPanel> {
|
|
|
399
411
|
_buildDesktopSection(controller),
|
|
400
412
|
const SizedBox(height: 16),
|
|
401
413
|
],
|
|
414
|
+
if (_matchesSettingsSection(
|
|
415
|
+
searchQuery,
|
|
416
|
+
_securitySettingsSection,
|
|
417
|
+
)) ...<Widget>[
|
|
418
|
+
_buildSecuritySection(context, controller),
|
|
419
|
+
const SizedBox(height: 16),
|
|
420
|
+
],
|
|
402
421
|
if (_matchesSettingsSection(
|
|
403
422
|
searchQuery,
|
|
404
423
|
_diagnosticsSettingsSection,
|
|
@@ -1492,6 +1511,48 @@ class _SettingsPanelState extends State<SettingsPanel> {
|
|
|
1492
1511
|
);
|
|
1493
1512
|
}
|
|
1494
1513
|
|
|
1514
|
+
Widget _buildSecuritySection(BuildContext context, NeoAgentController controller) {
|
|
1515
|
+
return Card(
|
|
1516
|
+
elevation: 0,
|
|
1517
|
+
shape: RoundedRectangleBorder(
|
|
1518
|
+
borderRadius: BorderRadius.circular(12),
|
|
1519
|
+
side: BorderSide(color: Theme.of(context).colorScheme.outlineVariant),
|
|
1520
|
+
),
|
|
1521
|
+
child: Column(
|
|
1522
|
+
crossAxisAlignment: CrossAxisAlignment.start,
|
|
1523
|
+
children: <Widget>[
|
|
1524
|
+
ListTile(
|
|
1525
|
+
leading: const Icon(Icons.shield_outlined),
|
|
1526
|
+
title: const Text('Security', style: TextStyle(fontWeight: FontWeight.bold)),
|
|
1527
|
+
subtitle: const Text('Tool allowlists, approval gates, and process isolation.'),
|
|
1528
|
+
trailing: const SizedBox.shrink(),
|
|
1529
|
+
),
|
|
1530
|
+
const Divider(height: 1),
|
|
1531
|
+
ListTile(
|
|
1532
|
+
leading: const Icon(Icons.checklist_outlined),
|
|
1533
|
+
title: const Text('Tool Permissions'),
|
|
1534
|
+
subtitle: const Text('Set block / ask / allow per tool category, or pick a global mode.'),
|
|
1535
|
+
trailing: Row(
|
|
1536
|
+
mainAxisSize: MainAxisSize.min,
|
|
1537
|
+
children: const <Widget>[
|
|
1538
|
+
Icon(Icons.shield_rounded, size: 16, color: Colors.green),
|
|
1539
|
+
SizedBox(width: 4),
|
|
1540
|
+
Icon(Icons.chevron_right),
|
|
1541
|
+
],
|
|
1542
|
+
),
|
|
1543
|
+
onTap: () {
|
|
1544
|
+
Navigator.of(context).push(
|
|
1545
|
+
MaterialPageRoute<void>(
|
|
1546
|
+
builder: (_) => MainSecurity(controller: controller),
|
|
1547
|
+
),
|
|
1548
|
+
);
|
|
1549
|
+
},
|
|
1550
|
+
),
|
|
1551
|
+
],
|
|
1552
|
+
),
|
|
1553
|
+
);
|
|
1554
|
+
}
|
|
1555
|
+
|
|
1495
1556
|
Widget _buildDiagnosticsSection(NeoAgentController controller) {
|
|
1496
1557
|
return Card(
|
|
1497
1558
|
child: Padding(
|
|
@@ -1421,15 +1421,29 @@ class BackendClient {
|
|
|
1421
1421
|
return getList(baseUrl, '/api/memory/memories$query');
|
|
1422
1422
|
}
|
|
1423
1423
|
|
|
1424
|
-
Future<List<Map<String, dynamic>>>
|
|
1424
|
+
Future<List<Map<String, dynamic>>> recallMemory(
|
|
1425
1425
|
String baseUrl,
|
|
1426
1426
|
String query, {
|
|
1427
|
+
int limit = 8,
|
|
1427
1428
|
String? agentId,
|
|
1428
1429
|
}) async {
|
|
1429
1430
|
return postList(
|
|
1430
1431
|
baseUrl,
|
|
1431
|
-
'/api/memory/memories/recall',
|
|
1432
|
-
|
|
1432
|
+
_withAgentQuery('/api/memory/memories/recall', agentId),
|
|
1433
|
+
{'query': query, 'limit': limit},
|
|
1434
|
+
);
|
|
1435
|
+
}
|
|
1436
|
+
|
|
1437
|
+
Future<Map<String, dynamic>> inspectMemory(
|
|
1438
|
+
String baseUrl,
|
|
1439
|
+
String query, {
|
|
1440
|
+
int limit = 20,
|
|
1441
|
+
String? agentId,
|
|
1442
|
+
}) async {
|
|
1443
|
+
return postMap(
|
|
1444
|
+
baseUrl,
|
|
1445
|
+
_withAgentQuery('/api/memory/memories/inspect', agentId),
|
|
1446
|
+
{'query': query, 'limit': limit},
|
|
1433
1447
|
);
|
|
1434
1448
|
}
|
|
1435
1449
|
|
|
@@ -2004,6 +2018,49 @@ class BackendClient {
|
|
|
2004
2018
|
|
|
2005
2019
|
throw BackendException(message, statusCode: response.statusCode);
|
|
2006
2020
|
}
|
|
2021
|
+
|
|
2022
|
+
// ── Tool security ──────────────────────────────────────────────────────────
|
|
2023
|
+
|
|
2024
|
+
Future<Map<String, dynamic>> fetchSecurityPolicies(String baseUrl) async {
|
|
2025
|
+
return getMap(baseUrl, '/api/security/policies');
|
|
2026
|
+
}
|
|
2027
|
+
|
|
2028
|
+
Future<Map<String, dynamic>> fetchSecurityMode(String baseUrl) async {
|
|
2029
|
+
return getMap(baseUrl, '/api/security/mode');
|
|
2030
|
+
}
|
|
2031
|
+
|
|
2032
|
+
Future<Map<String, dynamic>> saveSecurityMode(String baseUrl, String mode) async {
|
|
2033
|
+
return putMap(baseUrl, '/api/security/mode', <String, dynamic>{'mode': mode});
|
|
2034
|
+
}
|
|
2035
|
+
|
|
2036
|
+
Future<Map<String, dynamic>> saveSecurityPolicy(
|
|
2037
|
+
String baseUrl, {
|
|
2038
|
+
required String category,
|
|
2039
|
+
required String policy,
|
|
2040
|
+
}) async {
|
|
2041
|
+
return putMap(baseUrl, '/api/security/policies', <String, dynamic>{
|
|
2042
|
+
'category': category,
|
|
2043
|
+
'policy': policy,
|
|
2044
|
+
});
|
|
2045
|
+
}
|
|
2046
|
+
|
|
2047
|
+
Future<Map<String, dynamic>> resolveToolApproval(
|
|
2048
|
+
String baseUrl, {
|
|
2049
|
+
required String approvalId,
|
|
2050
|
+
required String decision,
|
|
2051
|
+
required String scope,
|
|
2052
|
+
String? runId,
|
|
2053
|
+
String? toolName,
|
|
2054
|
+
Map<String, dynamic>? toolArgs,
|
|
2055
|
+
}) async {
|
|
2056
|
+
return postMap(baseUrl, '/api/security/approvals/$approvalId', <String, dynamic>{
|
|
2057
|
+
'decision': decision,
|
|
2058
|
+
'scope': scope,
|
|
2059
|
+
if (runId != null) 'runId': runId,
|
|
2060
|
+
if (toolName != null) 'toolName': toolName,
|
|
2061
|
+
if (toolArgs != null) 'toolArgs': toolArgs,
|
|
2062
|
+
});
|
|
2063
|
+
}
|
|
2007
2064
|
}
|
|
2008
2065
|
|
|
2009
2066
|
class BackendException implements Exception {
|
|
@@ -9,6 +9,7 @@ import audioplayers_darwin
|
|
|
9
9
|
import connectivity_plus
|
|
10
10
|
import desktop_audio_capture
|
|
11
11
|
import file_picker
|
|
12
|
+
import flutter_local_notifications
|
|
12
13
|
import flutter_secure_storage_macos
|
|
13
14
|
import geolocator_apple
|
|
14
15
|
import hotkey_manager_macos
|
|
@@ -29,6 +30,7 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
|
|
29
30
|
ConnectivityPlusPlugin.register(with: registry.registrar(forPlugin: "ConnectivityPlusPlugin"))
|
|
30
31
|
AudioCapturePlugin.register(with: registry.registrar(forPlugin: "AudioCapturePlugin"))
|
|
31
32
|
FilePickerPlugin.register(with: registry.registrar(forPlugin: "FilePickerPlugin"))
|
|
33
|
+
FlutterLocalNotificationsPlugin.register(with: registry.registrar(forPlugin: "FlutterLocalNotificationsPlugin"))
|
|
32
34
|
FlutterSecureStoragePlugin.register(with: registry.registrar(forPlugin: "FlutterSecureStoragePlugin"))
|
|
33
35
|
GeolocatorPlugin.register(with: registry.registrar(forPlugin: "GeolocatorPlugin"))
|
|
34
36
|
HotkeyManagerMacosPlugin.register(with: registry.registrar(forPlugin: "HotkeyManagerMacosPlugin"))
|
package/flutter_app/pubspec.lock
CHANGED
|
@@ -277,6 +277,30 @@ packages:
|
|
|
277
277
|
url: "https://pub.dev"
|
|
278
278
|
source: hosted
|
|
279
279
|
version: "5.0.0"
|
|
280
|
+
flutter_local_notifications:
|
|
281
|
+
dependency: "direct main"
|
|
282
|
+
description:
|
|
283
|
+
name: flutter_local_notifications
|
|
284
|
+
sha256: ef41ae901e7529e52934feba19ed82827b11baa67336829564aeab3129460610
|
|
285
|
+
url: "https://pub.dev"
|
|
286
|
+
source: hosted
|
|
287
|
+
version: "18.0.1"
|
|
288
|
+
flutter_local_notifications_linux:
|
|
289
|
+
dependency: transitive
|
|
290
|
+
description:
|
|
291
|
+
name: flutter_local_notifications_linux
|
|
292
|
+
sha256: "8f685642876742c941b29c32030f6f4f6dacd0e4eaecb3efbb187d6a3812ca01"
|
|
293
|
+
url: "https://pub.dev"
|
|
294
|
+
source: hosted
|
|
295
|
+
version: "5.0.0"
|
|
296
|
+
flutter_local_notifications_platform_interface:
|
|
297
|
+
dependency: transitive
|
|
298
|
+
description:
|
|
299
|
+
name: flutter_local_notifications_platform_interface
|
|
300
|
+
sha256: "6c5b83c86bf819cdb177a9247a3722067dd8cc6313827ce7c77a4b238a26fd52"
|
|
301
|
+
url: "https://pub.dev"
|
|
302
|
+
source: hosted
|
|
303
|
+
version: "8.0.0"
|
|
280
304
|
flutter_markdown:
|
|
281
305
|
dependency: "direct main"
|
|
282
306
|
description:
|
|
@@ -1035,6 +1059,14 @@ packages:
|
|
|
1035
1059
|
url: "https://pub.dev"
|
|
1036
1060
|
source: hosted
|
|
1037
1061
|
version: "0.7.11"
|
|
1062
|
+
timezone:
|
|
1063
|
+
dependency: transitive
|
|
1064
|
+
description:
|
|
1065
|
+
name: timezone
|
|
1066
|
+
sha256: dd14a3b83cfd7cb19e7888f1cbc20f258b8d71b54c06f79ac585f14093a287d1
|
|
1067
|
+
url: "https://pub.dev"
|
|
1068
|
+
source: hosted
|
|
1069
|
+
version: "0.10.1"
|
|
1038
1070
|
tray_manager:
|
|
1039
1071
|
dependency: "direct main"
|
|
1040
1072
|
description:
|
package/flutter_app/pubspec.yaml
CHANGED
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
function migrateMemoryEmbeddingIndex(db) {
|
|
4
|
+
db.exec(`
|
|
5
|
+
CREATE TABLE IF NOT EXISTS memory_embedding_bands (
|
|
6
|
+
memory_id TEXT NOT NULL,
|
|
7
|
+
user_id INTEGER NOT NULL,
|
|
8
|
+
agent_id TEXT NOT NULL,
|
|
9
|
+
dimension INTEGER NOT NULL,
|
|
10
|
+
index_version INTEGER NOT NULL DEFAULT 3,
|
|
11
|
+
band_index INTEGER NOT NULL,
|
|
12
|
+
band_value INTEGER NOT NULL,
|
|
13
|
+
updated_at TEXT DEFAULT (datetime('now')),
|
|
14
|
+
PRIMARY KEY (memory_id, band_index),
|
|
15
|
+
FOREIGN KEY (memory_id) REFERENCES memories(id) ON DELETE CASCADE,
|
|
16
|
+
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
|
|
17
|
+
);
|
|
18
|
+
|
|
19
|
+
CREATE INDEX IF NOT EXISTS idx_memory_embedding_bands_lookup
|
|
20
|
+
ON memory_embedding_bands(
|
|
21
|
+
user_id,
|
|
22
|
+
agent_id,
|
|
23
|
+
dimension,
|
|
24
|
+
band_index,
|
|
25
|
+
band_value
|
|
26
|
+
);
|
|
27
|
+
`);
|
|
28
|
+
const columns = new Set(
|
|
29
|
+
db.prepare('PRAGMA table_info(memory_embedding_bands)').all()
|
|
30
|
+
.map((column) => column.name),
|
|
31
|
+
);
|
|
32
|
+
if (!columns.has('index_version')) {
|
|
33
|
+
db.exec('ALTER TABLE memory_embedding_bands ADD COLUMN index_version INTEGER');
|
|
34
|
+
}
|
|
35
|
+
db.exec(`
|
|
36
|
+
DROP INDEX IF EXISTS idx_memory_embedding_bands_lookup;
|
|
37
|
+
CREATE INDEX idx_memory_embedding_bands_lookup
|
|
38
|
+
ON memory_embedding_bands(
|
|
39
|
+
user_id,
|
|
40
|
+
agent_id,
|
|
41
|
+
dimension,
|
|
42
|
+
index_version,
|
|
43
|
+
band_index,
|
|
44
|
+
band_value
|
|
45
|
+
);
|
|
46
|
+
`);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function migrateMemoryProvenance(db) {
|
|
50
|
+
db.exec(`
|
|
51
|
+
CREATE TABLE IF NOT EXISTS memory_source_chunks (
|
|
52
|
+
id TEXT PRIMARY KEY,
|
|
53
|
+
document_id TEXT NOT NULL,
|
|
54
|
+
user_id INTEGER NOT NULL,
|
|
55
|
+
agent_id TEXT NOT NULL,
|
|
56
|
+
chunk_index INTEGER NOT NULL,
|
|
57
|
+
char_start INTEGER NOT NULL,
|
|
58
|
+
char_end INTEGER NOT NULL,
|
|
59
|
+
content TEXT NOT NULL,
|
|
60
|
+
content_hash TEXT NOT NULL,
|
|
61
|
+
metadata_json TEXT DEFAULT '{}',
|
|
62
|
+
created_at TEXT DEFAULT (datetime('now')),
|
|
63
|
+
updated_at TEXT DEFAULT (datetime('now')),
|
|
64
|
+
FOREIGN KEY (document_id) REFERENCES memory_ingestion_documents(id) ON DELETE CASCADE,
|
|
65
|
+
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
|
|
66
|
+
UNIQUE(document_id, content_hash)
|
|
67
|
+
);
|
|
68
|
+
|
|
69
|
+
CREATE TABLE IF NOT EXISTS memory_source_links (
|
|
70
|
+
memory_id TEXT NOT NULL,
|
|
71
|
+
chunk_id TEXT NOT NULL,
|
|
72
|
+
source_document_id TEXT NOT NULL,
|
|
73
|
+
source_timestamp TEXT,
|
|
74
|
+
relevance_score REAL DEFAULT 1,
|
|
75
|
+
extraction_method TEXT DEFAULT 'source_chunk',
|
|
76
|
+
metadata_json TEXT DEFAULT '{}',
|
|
77
|
+
created_at TEXT DEFAULT (datetime('now')),
|
|
78
|
+
PRIMARY KEY (memory_id, chunk_id),
|
|
79
|
+
FOREIGN KEY (memory_id) REFERENCES memories(id) ON DELETE CASCADE,
|
|
80
|
+
FOREIGN KEY (chunk_id) REFERENCES memory_source_chunks(id) ON DELETE CASCADE,
|
|
81
|
+
FOREIGN KEY (source_document_id) REFERENCES memory_ingestion_documents(id) ON DELETE CASCADE
|
|
82
|
+
);
|
|
83
|
+
|
|
84
|
+
CREATE INDEX IF NOT EXISTS idx_memory_source_chunks_document
|
|
85
|
+
ON memory_source_chunks(document_id, chunk_index);
|
|
86
|
+
CREATE INDEX IF NOT EXISTS idx_memory_source_links_memory
|
|
87
|
+
ON memory_source_links(memory_id);
|
|
88
|
+
CREATE INDEX IF NOT EXISTS idx_memory_source_links_document
|
|
89
|
+
ON memory_source_links(source_document_id);
|
|
90
|
+
`);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function migrateMemoryRelations(db) {
|
|
94
|
+
db.exec(`
|
|
95
|
+
CREATE TABLE IF NOT EXISTS memory_relations (
|
|
96
|
+
id TEXT PRIMARY KEY,
|
|
97
|
+
user_id INTEGER NOT NULL,
|
|
98
|
+
agent_id TEXT,
|
|
99
|
+
from_memory_id TEXT NOT NULL,
|
|
100
|
+
to_memory_id TEXT NOT NULL,
|
|
101
|
+
relation_type TEXT NOT NULL CHECK(relation_type IN ('updates', 'extends', 'derives')),
|
|
102
|
+
confidence REAL DEFAULT 0.7,
|
|
103
|
+
metadata_json TEXT DEFAULT '{}',
|
|
104
|
+
created_at TEXT DEFAULT (datetime('now')),
|
|
105
|
+
UNIQUE(from_memory_id, to_memory_id, relation_type),
|
|
106
|
+
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
|
|
107
|
+
FOREIGN KEY (agent_id) REFERENCES agents(id) ON DELETE SET NULL,
|
|
108
|
+
FOREIGN KEY (from_memory_id) REFERENCES memories(id) ON DELETE CASCADE,
|
|
109
|
+
FOREIGN KEY (to_memory_id) REFERENCES memories(id) ON DELETE CASCADE
|
|
110
|
+
);
|
|
111
|
+
|
|
112
|
+
CREATE INDEX IF NOT EXISTS idx_memory_relations_from
|
|
113
|
+
ON memory_relations(user_id, agent_id, from_memory_id);
|
|
114
|
+
CREATE INDEX IF NOT EXISTS idx_memory_relations_to
|
|
115
|
+
ON memory_relations(user_id, agent_id, to_memory_id);
|
|
116
|
+
`);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function migrateMemoryRetrievalEvents(db) {
|
|
120
|
+
db.exec(`
|
|
121
|
+
CREATE TABLE IF NOT EXISTS memory_retrieval_events (
|
|
122
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
123
|
+
user_id INTEGER NOT NULL,
|
|
124
|
+
agent_id TEXT NOT NULL,
|
|
125
|
+
query_hash TEXT NOT NULL,
|
|
126
|
+
scope_type TEXT NOT NULL,
|
|
127
|
+
scope_id TEXT,
|
|
128
|
+
requested_k INTEGER NOT NULL,
|
|
129
|
+
candidate_count INTEGER DEFAULT 0,
|
|
130
|
+
semantic_candidate_count INTEGER DEFAULT 0,
|
|
131
|
+
lexical_candidate_count INTEGER DEFAULT 0,
|
|
132
|
+
entity_candidate_count INTEGER DEFAULT 0,
|
|
133
|
+
relation_candidate_count INTEGER DEFAULT 0,
|
|
134
|
+
result_count INTEGER DEFAULT 0,
|
|
135
|
+
result_ids_json TEXT DEFAULT '[]',
|
|
136
|
+
context_tokens_estimate INTEGER DEFAULT 0,
|
|
137
|
+
latency_ms REAL DEFAULT 0,
|
|
138
|
+
created_at TEXT DEFAULT (datetime('now')),
|
|
139
|
+
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
|
|
140
|
+
);
|
|
141
|
+
|
|
142
|
+
CREATE INDEX IF NOT EXISTS idx_memory_retrieval_events_user
|
|
143
|
+
ON memory_retrieval_events(user_id, agent_id, created_at DESC);
|
|
144
|
+
|
|
145
|
+
CREATE TABLE IF NOT EXISTS memory_retrieval_enhancements (
|
|
146
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
147
|
+
user_id INTEGER NOT NULL,
|
|
148
|
+
agent_id TEXT NOT NULL,
|
|
149
|
+
run_id TEXT,
|
|
150
|
+
query_hash TEXT NOT NULL,
|
|
151
|
+
trigger_reason TEXT NOT NULL,
|
|
152
|
+
plan_json TEXT,
|
|
153
|
+
initial_count INTEGER DEFAULT 0,
|
|
154
|
+
merged_count INTEGER DEFAULT 0,
|
|
155
|
+
result_ids_json TEXT DEFAULT '[]',
|
|
156
|
+
latency_ms REAL DEFAULT 0,
|
|
157
|
+
created_at TEXT DEFAULT (datetime('now')),
|
|
158
|
+
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
|
|
159
|
+
FOREIGN KEY (run_id) REFERENCES agent_runs(id) ON DELETE SET NULL
|
|
160
|
+
);
|
|
161
|
+
|
|
162
|
+
CREATE INDEX IF NOT EXISTS idx_memory_retrieval_enhancements_user
|
|
163
|
+
ON memory_retrieval_enhancements(user_id, agent_id, created_at DESC);
|
|
164
|
+
`);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
function migrateMemoryEmbeddingMetadata(db) {
|
|
168
|
+
const columns = new Set(
|
|
169
|
+
db.prepare('PRAGMA table_info(memories)').all().map((column) => column.name),
|
|
170
|
+
);
|
|
171
|
+
const additions = [
|
|
172
|
+
['embedding_provider', 'TEXT'],
|
|
173
|
+
['embedding_model', 'TEXT'],
|
|
174
|
+
['embedding_dimensions', 'INTEGER'],
|
|
175
|
+
['embedded_at', 'TEXT'],
|
|
176
|
+
];
|
|
177
|
+
for (const [name, type] of additions) {
|
|
178
|
+
if (!columns.has(name)) {
|
|
179
|
+
db.exec(`ALTER TABLE memories ADD COLUMN ${name} ${type}`);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
try {
|
|
183
|
+
db.exec(`
|
|
184
|
+
UPDATE memories
|
|
185
|
+
SET embedding_dimensions = json_array_length(embedding),
|
|
186
|
+
embedding_provider = COALESCE(embedding_provider, 'legacy_unknown')
|
|
187
|
+
WHERE embedding IS NOT NULL AND embedding_dimensions IS NULL
|
|
188
|
+
`);
|
|
189
|
+
} catch {
|
|
190
|
+
// JSON1 may be unavailable. New writes still carry complete metadata.
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
function migrateToolPermissions(db) {
|
|
195
|
+
db.exec(`
|
|
196
|
+
CREATE TABLE IF NOT EXISTS tool_policies (
|
|
197
|
+
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
|
198
|
+
category TEXT NOT NULL,
|
|
199
|
+
policy TEXT NOT NULL CHECK(policy IN ('allow','deny','require_approval')),
|
|
200
|
+
updated_at TEXT DEFAULT (datetime('now')),
|
|
201
|
+
PRIMARY KEY (user_id, category)
|
|
202
|
+
);
|
|
203
|
+
|
|
204
|
+
CREATE TABLE IF NOT EXISTS tool_approval_log (
|
|
205
|
+
id TEXT PRIMARY KEY,
|
|
206
|
+
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
|
207
|
+
run_id TEXT NOT NULL,
|
|
208
|
+
tool_name TEXT NOT NULL,
|
|
209
|
+
tool_args_json TEXT,
|
|
210
|
+
decision TEXT NOT NULL CHECK(decision IN ('approved','denied','timeout')),
|
|
211
|
+
scope TEXT NOT NULL CHECK(scope IN ('once','session')),
|
|
212
|
+
decided_at TEXT DEFAULT (datetime('now'))
|
|
213
|
+
);
|
|
214
|
+
|
|
215
|
+
CREATE INDEX IF NOT EXISTS idx_approval_log_user
|
|
216
|
+
ON tool_approval_log(user_id, decided_at DESC);
|
|
217
|
+
`);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
function runSchemaMigrations(db) {
|
|
221
|
+
migrateMemoryEmbeddingIndex(db);
|
|
222
|
+
migrateMemoryProvenance(db);
|
|
223
|
+
migrateMemoryRelations(db);
|
|
224
|
+
migrateMemoryRetrievalEvents(db);
|
|
225
|
+
migrateMemoryEmbeddingMetadata(db);
|
|
226
|
+
migrateToolPermissions(db);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
module.exports = {
|
|
230
|
+
migrateMemoryEmbeddingIndex,
|
|
231
|
+
migrateMemoryProvenance,
|
|
232
|
+
migrateMemoryRelations,
|
|
233
|
+
migrateMemoryRetrievalEvents,
|
|
234
|
+
migrateMemoryEmbeddingMetadata,
|
|
235
|
+
migrateToolPermissions,
|
|
236
|
+
runSchemaMigrations,
|
|
237
|
+
};
|
package/package.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "neoagent",
|
|
3
|
-
"version": "2.4.4-beta.
|
|
3
|
+
"version": "2.4.4-beta.5",
|
|
4
4
|
"description": "Proactive personal AI agent with no limits",
|
|
5
5
|
"license": "AGPL-3.0-only",
|
|
6
6
|
"main": "server/index.js",
|
|
7
7
|
"engines": {
|
|
8
|
-
"node": ">=
|
|
8
|
+
"node": ">=18.0.0"
|
|
9
9
|
},
|
|
10
10
|
"bin": {
|
|
11
11
|
"neoagent": "bin/neoagent.js"
|
|
@@ -52,6 +52,8 @@
|
|
|
52
52
|
"flutter:test:unit": "cd flutter_app && flutter test ../test/flutter/unit",
|
|
53
53
|
"flutter:test:widget": "cd flutter_app && flutter test ../test/flutter/widget",
|
|
54
54
|
"benchmark:tokens": "node scripts/benchmark-token-cost.js",
|
|
55
|
+
"benchmark:memory": "node scripts/benchmark-memory.js",
|
|
56
|
+
"benchmark:memorybench:install": "node scripts/install-memorybench-provider.js",
|
|
55
57
|
"release": "npx semantic-release"
|
|
56
58
|
},
|
|
57
59
|
"repository": {
|
package/server/db/database.js
CHANGED
|
@@ -7,6 +7,7 @@ const {
|
|
|
7
7
|
encryptValue,
|
|
8
8
|
isEncryptedValue,
|
|
9
9
|
} = require('../services/integrations/secrets');
|
|
10
|
+
const { runSchemaMigrations } = require('../../lib/schema_migrations');
|
|
10
11
|
ensureRuntimeDirs();
|
|
11
12
|
|
|
12
13
|
const DB_PATH = path.join(DATA_DIR, 'neoagent.db');
|
|
@@ -1075,6 +1076,8 @@ db.exec(`
|
|
|
1075
1076
|
END;
|
|
1076
1077
|
`);
|
|
1077
1078
|
|
|
1079
|
+
runSchemaMigrations(db);
|
|
1080
|
+
|
|
1078
1081
|
try {
|
|
1079
1082
|
db.exec(`
|
|
1080
1083
|
CREATE VIRTUAL TABLE IF NOT EXISTS screen_history_fts USING fts5(
|
package/server/http/routes.js
CHANGED
|
@@ -34,7 +34,8 @@ const routeRegistry = [
|
|
|
34
34
|
{ basePath: '/api/wearable', modulePath: '../routes/wearable' },
|
|
35
35
|
{ basePath: '/api/mobile/health', modulePath: '../routes/mobile-health' },
|
|
36
36
|
{ basePath: '/api/screen-history', modulePath: '../routes/screenHistory' },
|
|
37
|
-
{ basePath: '/api/triggers', modulePath: '../routes/triggers' }
|
|
37
|
+
{ basePath: '/api/triggers', modulePath: '../routes/triggers' },
|
|
38
|
+
{ basePath: '/api/security', modulePath: '../routes/security' },
|
|
38
39
|
];
|
|
39
40
|
|
|
40
41
|
function registerApiRoutes(app) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
c2289b3fa7982a602c361af43c1bfaec
|
|
@@ -5943,6 +5943,67 @@ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
|
5943
5943
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
5944
5944
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
5945
5945
|
|
|
5946
|
+
--------------------------------------------------------------------------------
|
|
5947
|
+
flutter_local_notifications
|
|
5948
|
+
flutter_local_notifications_linux
|
|
5949
|
+
|
|
5950
|
+
Copyright 2018 Michael Bui. All rights reserved.
|
|
5951
|
+
|
|
5952
|
+
Redistribution and use in source and binary forms, with or without
|
|
5953
|
+
modification, are permitted provided that the following conditions are
|
|
5954
|
+
met:
|
|
5955
|
+
|
|
5956
|
+
* Redistributions of source code must retain the above copyright
|
|
5957
|
+
notice, this list of conditions and the following disclaimer.
|
|
5958
|
+
* Redistributions in binary form must reproduce the above
|
|
5959
|
+
copyright notice, this list of conditions and the following disclaimer
|
|
5960
|
+
in the documentation and/or other materials provided with the
|
|
5961
|
+
distribution.
|
|
5962
|
+
* Neither the name of the copyright holder nor the names of its
|
|
5963
|
+
contributors may be used to endorse or promote products derived from
|
|
5964
|
+
this software without specific prior written permission.
|
|
5965
|
+
|
|
5966
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
5967
|
+
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
5968
|
+
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
5969
|
+
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
5970
|
+
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
5971
|
+
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
5972
|
+
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
5973
|
+
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
5974
|
+
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
5975
|
+
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
5976
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
5977
|
+
--------------------------------------------------------------------------------
|
|
5978
|
+
flutter_local_notifications_platform_interface
|
|
5979
|
+
|
|
5980
|
+
Copyright 2020 Michael Bui. All rights reserved.
|
|
5981
|
+
|
|
5982
|
+
Redistribution and use in source and binary forms, with or without
|
|
5983
|
+
modification, are permitted provided that the following conditions are
|
|
5984
|
+
met:
|
|
5985
|
+
|
|
5986
|
+
* Redistributions of source code must retain the above copyright
|
|
5987
|
+
notice, this list of conditions and the following disclaimer.
|
|
5988
|
+
* Redistributions in binary form must reproduce the above
|
|
5989
|
+
copyright notice, this list of conditions and the following disclaimer
|
|
5990
|
+
in the documentation and/or other materials provided with the
|
|
5991
|
+
distribution.
|
|
5992
|
+
* Neither the name of the copyright holder nor the names of its
|
|
5993
|
+
contributors may be used to endorse or promote products derived from
|
|
5994
|
+
this software without specific prior written permission.
|
|
5995
|
+
|
|
5996
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
5997
|
+
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
5998
|
+
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
5999
|
+
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
6000
|
+
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
6001
|
+
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
6002
|
+
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
6003
|
+
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
6004
|
+
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
6005
|
+
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
6006
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
5946
6007
|
--------------------------------------------------------------------------------
|
|
5947
6008
|
flutter_secure_storage
|
|
5948
6009
|
flutter_secure_storage_macos
|
|
@@ -29226,6 +29287,31 @@ The above copyright notice and this permission notice shall be included in all c
|
|
|
29226
29287
|
|
|
29227
29288
|
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.
|
|
29228
29289
|
--------------------------------------------------------------------------------
|
|
29290
|
+
timezone
|
|
29291
|
+
|
|
29292
|
+
Copyright (c) 2014, timezone project authors.
|
|
29293
|
+
All rights reserved.
|
|
29294
|
+
|
|
29295
|
+
Redistribution and use in source and binary forms, with or without
|
|
29296
|
+
modification, are permitted provided that the following conditions are met:
|
|
29297
|
+
|
|
29298
|
+
* Redistributions of source code must retain the above copyright
|
|
29299
|
+
notice, this list of conditions and the following disclaimer.
|
|
29300
|
+
* Redistributions in binary form must reproduce the above copyright
|
|
29301
|
+
notice, this list of conditions and the following disclaimer in the
|
|
29302
|
+
documentation and/or other materials provided with the distribution.
|
|
29303
|
+
|
|
29304
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
29305
|
+
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
29306
|
+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
29307
|
+
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
|
29308
|
+
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
29309
|
+
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
29310
|
+
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
29311
|
+
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
29312
|
+
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
29313
|
+
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
29314
|
+
--------------------------------------------------------------------------------
|
|
29229
29315
|
tray_manager
|
|
29230
29316
|
window_manager
|
|
29231
29317
|
|
|
Binary file
|
|
@@ -37,6 +37,6 @@ _flutter.buildConfig = {"engineRevision":"77e2e94772b6eb43759e34ed1ad7da4674e19c
|
|
|
37
37
|
|
|
38
38
|
_flutter.loader.load({
|
|
39
39
|
serviceWorkerSettings: {
|
|
40
|
-
serviceWorkerVersion: "
|
|
40
|
+
serviceWorkerVersion: "2175258401" /* Flutter's service worker is deprecated and will be removed in a future Flutter release. */
|
|
41
41
|
}
|
|
42
42
|
});
|