neoagent 2.3.1-beta.25 → 2.3.1-beta.26
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/package.json
CHANGED
|
@@ -69,9 +69,11 @@ ensureSessionStoreSchema(sessionsDb);
|
|
|
69
69
|
function buildHelmetOptions({ secureCookies }) {
|
|
70
70
|
const wsConnectSrc = secureCookies ? ['wss:'] : ['ws:', 'wss:'];
|
|
71
71
|
const isDevelopment = String(process.env.NODE_ENV || '').trim() === 'development';
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
const
|
|
72
|
+
// Flutter web (CanvasKit) requires external script/connect sources and wasm eval.
|
|
73
|
+
// Keep strict overrides available via env for hardened deployments.
|
|
74
|
+
const allowUnsafeEval = boolEnv('NEOAGENT_CSP_ALLOW_UNSAFE_EVAL', true);
|
|
75
|
+
const allowExternalScriptCdn = boolEnv('NEOAGENT_CSP_ALLOW_EXTERNAL_SCRIPT_CDN', true);
|
|
76
|
+
const allowExternalConnect = boolEnv('NEOAGENT_CSP_ALLOW_EXTERNAL_CONNECT', true);
|
|
75
77
|
|
|
76
78
|
const scriptSrc = ["'self'", "'unsafe-inline'", 'blob:'];
|
|
77
79
|
if (allowUnsafeEval) {
|
|
@@ -83,7 +85,7 @@ function buildHelmetOptions({ secureCookies }) {
|
|
|
83
85
|
|
|
84
86
|
const connectSrc = ["'self'", ...wsConnectSrc];
|
|
85
87
|
if (allowExternalConnect) {
|
|
86
|
-
connectSrc.push('https://fonts.googleapis.com', 'https://fonts.gstatic.com', 'https://www.gstatic.com');
|
|
88
|
+
connectSrc.push('https://fonts.googleapis.com', 'https://fonts.gstatic.com', 'https://www.gstatic.com', 'https://cdn.jsdelivr.net');
|
|
87
89
|
}
|
|
88
90
|
|
|
89
91
|
return {
|
|
@@ -37,6 +37,6 @@ _flutter.buildConfig = {"engineRevision":"59aa584fdf100e6c78c785d8a5b565d1de4b48
|
|
|
37
37
|
|
|
38
38
|
_flutter.loader.load({
|
|
39
39
|
serviceWorkerSettings: {
|
|
40
|
-
serviceWorkerVersion: "
|
|
40
|
+
serviceWorkerVersion: "753731712" /* Flutter's service worker is deprecated and will be removed in a future Flutter release. */
|
|
41
41
|
}
|
|
42
42
|
});
|
|
@@ -12,7 +12,7 @@ const { getErrorMessage } = require('../bootstrap_helpers');
|
|
|
12
12
|
const execAsync = promisify(exec);
|
|
13
13
|
|
|
14
14
|
class ScreenRecorder {
|
|
15
|
-
constructor() {
|
|
15
|
+
constructor(options = {}) {
|
|
16
16
|
this.intervalMs = 10000; // 10 seconds
|
|
17
17
|
this.intervalId = null;
|
|
18
18
|
this.cleanupIntervalId = null;
|
|
@@ -20,6 +20,9 @@ class ScreenRecorder {
|
|
|
20
20
|
this.isProcessing = false;
|
|
21
21
|
this.tempFilePath = path.join(os.tmpdir(), `neoagent-screen-${Date.now()}.png`);
|
|
22
22
|
this.lastBenignSkipAt = 0;
|
|
23
|
+
this.hasActiveRemoteCaptureSession = typeof options.hasActiveRemoteCaptureSession === 'function'
|
|
24
|
+
? options.hasActiveRemoteCaptureSession
|
|
25
|
+
: () => false;
|
|
23
26
|
}
|
|
24
27
|
|
|
25
28
|
_isCaptureInactiveApp(appName) {
|
|
@@ -94,6 +97,13 @@ class ScreenRecorder {
|
|
|
94
97
|
this.isProcessing = true;
|
|
95
98
|
|
|
96
99
|
try {
|
|
100
|
+
// Only capture while at least one external device/session is actively connected.
|
|
101
|
+
// This prevents host-level screenshots when no user-side capture source is live.
|
|
102
|
+
if (!this.hasActiveRemoteCaptureSession()) {
|
|
103
|
+
this._logBenignSkip('no active external capture session');
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
|
|
97
107
|
// Skip capture when the desktop session is inactive (e.g. locked screen).
|
|
98
108
|
let frontmostApp = '';
|
|
99
109
|
try {
|
|
@@ -430,10 +430,35 @@ function createWidgetService(app) {
|
|
|
430
430
|
}
|
|
431
431
|
|
|
432
432
|
function createScreenRecorder(app) {
|
|
433
|
+
const hasActiveRemoteCaptureSession = () => {
|
|
434
|
+
const desktopRegistry = app.locals.desktopCompanionRegistry;
|
|
435
|
+
if (desktopRegistry?.connectionsByUser instanceof Map) {
|
|
436
|
+
for (const userMap of desktopRegistry.connectionsByUser.values()) {
|
|
437
|
+
if (!(userMap instanceof Map)) continue;
|
|
438
|
+
for (const connection of userMap.values()) {
|
|
439
|
+
if (typeof connection?.isOpen === 'function' && connection.isOpen()) {
|
|
440
|
+
return true;
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
const extensionRegistry = app.locals.browserExtensionRegistry;
|
|
447
|
+
if (extensionRegistry?.connectionsByUser instanceof Map) {
|
|
448
|
+
for (const connection of extensionRegistry.connectionsByUser.values()) {
|
|
449
|
+
if (typeof connection?.isOpen === 'function' && connection.isOpen()) {
|
|
450
|
+
return true;
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
return false;
|
|
456
|
+
};
|
|
457
|
+
|
|
433
458
|
const screenRecorder = registerLocal(
|
|
434
459
|
app,
|
|
435
460
|
'screenRecorder',
|
|
436
|
-
new ScreenRecorder(),
|
|
461
|
+
new ScreenRecorder({ hasActiveRemoteCaptureSession }),
|
|
437
462
|
);
|
|
438
463
|
screenRecorder.start();
|
|
439
464
|
logServiceReady('Screen recorder started');
|