neoagent 2.4.1-beta.34 → 2.4.1-beta.35
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/.env.example +10 -3
- package/flutter_app/lib/main_admin.dart +13 -0
- package/flutter_app/lib/main_controller.dart +24 -6
- package/flutter_app/lib/main_models.dart +14 -0
- package/package.json +1 -1
- package/server/public/.last_build_id +1 -1
- package/server/public/flutter_bootstrap.js +1 -1
- package/server/public/main.dart.js +13767 -13696
- package/server/routes/mcp.js +29 -13
- package/server/routes/memory.js +1 -0
- package/server/services/ai/engine.js +15 -6
- package/server/services/ai/systemPrompt.js +28 -22
- package/server/services/ai/tools.js +12 -3
- package/server/services/desktop/screenRecorder.js +208 -98
- package/server/services/desktop/screen_recorder_support.js +46 -0
- package/server/services/manager.js +51 -53
- package/server/services/mcp/client.js +208 -268
- package/server/services/mcp/client_support.js +172 -0
- package/server/services/mcp/recovery.js +116 -0
- package/server/services/mcp/tool_operations.js +123 -0
- package/server/services/memory/ingestion.js +185 -370
- package/server/services/memory/ingestion_coverage.js +129 -0
- package/server/services/memory/ingestion_documents.js +123 -0
- package/server/services/memory/ingestion_support.js +171 -0
- package/server/services/messaging/automation.js +71 -134
- package/server/services/messaging/inbound_queue.js +111 -0
- package/server/services/messaging/typing_keepalive.js +110 -0
- package/server/services/tasks/runtime.js +133 -21
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const DEFAULT_CAPTURE_INTERVAL_MS = 10 * 1000;
|
|
4
|
+
const DEFAULT_RETENTION_DAYS = 7;
|
|
5
|
+
const CLEANUP_INTERVAL_MS = 24 * 60 * 60 * 1000;
|
|
6
|
+
const MIN_CAPTURE_INTERVAL_MS = 1000;
|
|
7
|
+
const MINIMUM_TEXT_LENGTH = 5;
|
|
8
|
+
const FRONTMOST_APP_SCRIPT = 'tell application "System Events" to get name of first application process whose frontmost is true';
|
|
9
|
+
|
|
10
|
+
function isExplicitlyEnabled(value) {
|
|
11
|
+
return ['1', 'true', 'on', 'yes'].includes(String(value || '').trim().toLowerCase());
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function parsePositiveInteger(value, name, fallback, minimum = 1) {
|
|
15
|
+
if (value == null || String(value).trim() === '') {
|
|
16
|
+
return fallback;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const parsed = Number(value);
|
|
20
|
+
if (!Number.isSafeInteger(parsed) || parsed < minimum) {
|
|
21
|
+
throw new Error(`${name} must be an integer greater than or equal to ${minimum}.`);
|
|
22
|
+
}
|
|
23
|
+
return parsed;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function hasOpenConnectionForUser(registry, userId) {
|
|
27
|
+
const connections = registry?.connectionsByUser?.get(String(userId));
|
|
28
|
+
if (connections instanceof Map) {
|
|
29
|
+
return Array.from(connections.values()).some(
|
|
30
|
+
(connection) => typeof connection?.isOpen === 'function' && connection.isOpen(),
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
return typeof connections?.isOpen === 'function' && connections.isOpen();
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
module.exports = {
|
|
37
|
+
CLEANUP_INTERVAL_MS,
|
|
38
|
+
DEFAULT_CAPTURE_INTERVAL_MS,
|
|
39
|
+
DEFAULT_RETENTION_DAYS,
|
|
40
|
+
FRONTMOST_APP_SCRIPT,
|
|
41
|
+
MINIMUM_TEXT_LENGTH,
|
|
42
|
+
MIN_CAPTURE_INTERVAL_MS,
|
|
43
|
+
hasOpenConnectionForUser,
|
|
44
|
+
isExplicitlyEnabled,
|
|
45
|
+
parsePositiveInteger,
|
|
46
|
+
};
|
|
@@ -24,7 +24,10 @@ const { WorkspaceManager } = require('./workspace/manager');
|
|
|
24
24
|
const { BrowserExtensionRegistry } = require('./browser/extension/registry');
|
|
25
25
|
const { DesktopCompanionRegistry } = require('./desktop/registry');
|
|
26
26
|
const { DesktopProvider } = require('./desktop/provider');
|
|
27
|
-
const {
|
|
27
|
+
const {
|
|
28
|
+
ScreenRecorder,
|
|
29
|
+
hasOpenConnectionForUser,
|
|
30
|
+
} = require('./desktop/screenRecorder');
|
|
28
31
|
const { WearableService } = require('./wearable/service');
|
|
29
32
|
const { getRuntimeValidation } = require('./runtime/validation');
|
|
30
33
|
const {
|
|
@@ -112,10 +115,11 @@ function createMemoryIngestionService(app, { memoryManager, integrationManager }
|
|
|
112
115
|
new MemoryIngestionService({
|
|
113
116
|
memoryManager,
|
|
114
117
|
integrationManager,
|
|
118
|
+
intervalMs: process.env.NEOAGENT_MEMORY_INGESTION_INTERVAL_MS || undefined,
|
|
115
119
|
}),
|
|
116
120
|
);
|
|
117
|
-
memoryIngestionService.start();
|
|
118
|
-
logServiceReady(
|
|
121
|
+
const status = memoryIngestionService.start();
|
|
122
|
+
logServiceReady(`Memory ingestion service started (${status.intervalMs}ms interval)`);
|
|
119
123
|
return memoryIngestionService;
|
|
120
124
|
}
|
|
121
125
|
|
|
@@ -368,44 +372,26 @@ function createWearableService(app) {
|
|
|
368
372
|
}
|
|
369
373
|
|
|
370
374
|
function createScreenRecorder(app) {
|
|
371
|
-
const
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
for (const connection of userMap.values()) {
|
|
377
|
-
if (typeof connection?.isOpen === 'function' && connection.isOpen()) {
|
|
378
|
-
return true;
|
|
379
|
-
}
|
|
380
|
-
}
|
|
381
|
-
}
|
|
382
|
-
}
|
|
383
|
-
|
|
384
|
-
const extensionRegistry = app.locals.browserExtensionRegistry;
|
|
385
|
-
if (extensionRegistry?.connectionsByUser instanceof Map) {
|
|
386
|
-
for (const value of extensionRegistry.connectionsByUser.values()) {
|
|
387
|
-
if (value instanceof Map) {
|
|
388
|
-
for (const connection of value.values()) {
|
|
389
|
-
if (typeof connection?.isOpen === 'function' && connection.isOpen()) {
|
|
390
|
-
return true;
|
|
391
|
-
}
|
|
392
|
-
}
|
|
393
|
-
} else if (typeof value?.isOpen === 'function' && value.isOpen()) {
|
|
394
|
-
return true;
|
|
395
|
-
}
|
|
396
|
-
}
|
|
397
|
-
}
|
|
398
|
-
|
|
399
|
-
return false;
|
|
375
|
+
const hasActiveCaptureSessionForUser = (userId) => {
|
|
376
|
+
return (
|
|
377
|
+
hasOpenConnectionForUser(app.locals.desktopCompanionRegistry, userId)
|
|
378
|
+
|| hasOpenConnectionForUser(app.locals.browserExtensionRegistry, userId)
|
|
379
|
+
);
|
|
400
380
|
};
|
|
401
381
|
|
|
402
382
|
const screenRecorder = registerLocal(
|
|
403
383
|
app,
|
|
404
384
|
'screenRecorder',
|
|
405
|
-
new ScreenRecorder({
|
|
385
|
+
new ScreenRecorder({ hasActiveCaptureSessionForUser }),
|
|
406
386
|
);
|
|
407
|
-
screenRecorder.start();
|
|
408
|
-
|
|
387
|
+
const status = screenRecorder.start();
|
|
388
|
+
if (status.state === 'running') {
|
|
389
|
+
logServiceReady(
|
|
390
|
+
`Screen recorder started for user ${status.ownerUserId} (${status.intervalMs}ms interval)`,
|
|
391
|
+
);
|
|
392
|
+
} else {
|
|
393
|
+
logServiceReady(`Screen recorder ${status.state}: ${status.reason}`);
|
|
394
|
+
}
|
|
409
395
|
return screenRecorder;
|
|
410
396
|
}
|
|
411
397
|
|
|
@@ -541,12 +527,16 @@ async function stopServices(app) {
|
|
|
541
527
|
console.log('[Services] Stopping services');
|
|
542
528
|
|
|
543
529
|
if (app.locals.taskRuntime) {
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
530
|
+
tasks.push(
|
|
531
|
+
Promise.resolve()
|
|
532
|
+
.then(() => app.locals.taskRuntime.stop())
|
|
533
|
+
.then((status) => {
|
|
534
|
+
logServiceReady(`Task runtime shutdown complete (${status.state})`);
|
|
535
|
+
})
|
|
536
|
+
.catch((err) => {
|
|
537
|
+
console.error('[Tasks] Stop error:', getErrorMessage(err));
|
|
538
|
+
}),
|
|
539
|
+
);
|
|
550
540
|
}
|
|
551
541
|
|
|
552
542
|
if (app.locals.streamHub) {
|
|
@@ -559,12 +549,16 @@ async function stopServices(app) {
|
|
|
559
549
|
}
|
|
560
550
|
|
|
561
551
|
if (app.locals.memoryIngestionService) {
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
552
|
+
tasks.push(
|
|
553
|
+
Promise.resolve()
|
|
554
|
+
.then(() => app.locals.memoryIngestionService.stop())
|
|
555
|
+
.then((status) => {
|
|
556
|
+
logServiceReady(`Memory ingestion shutdown complete (${status.state})`);
|
|
557
|
+
})
|
|
558
|
+
.catch((err) => {
|
|
559
|
+
console.error('[MemoryIngestion] Stop error:', getErrorMessage(err));
|
|
560
|
+
}),
|
|
561
|
+
);
|
|
568
562
|
}
|
|
569
563
|
|
|
570
564
|
if (app.locals.mcpClient) {
|
|
@@ -637,12 +631,16 @@ async function stopServices(app) {
|
|
|
637
631
|
}
|
|
638
632
|
|
|
639
633
|
if (app.locals.screenRecorder) {
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
634
|
+
tasks.push(
|
|
635
|
+
Promise.resolve()
|
|
636
|
+
.then(() => app.locals.screenRecorder.stop())
|
|
637
|
+
.then((status) => {
|
|
638
|
+
logServiceReady(`Screen recorder shutdown complete (${status.state})`);
|
|
639
|
+
})
|
|
640
|
+
.catch((err) => {
|
|
641
|
+
console.error('[ScreenRecorder] Stop error:', getErrorMessage(err));
|
|
642
|
+
}),
|
|
643
|
+
);
|
|
646
644
|
}
|
|
647
645
|
|
|
648
646
|
if (app.locals.browserExtensionRegistry) {
|