neoagent 2.1.18-beta.63 → 2.1.18-beta.65
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 -0
- package/lib/manager.js +4 -0
- package/package.json +1 -1
- package/server/http/middleware.js +5 -4
- package/server/index.js +32 -2
- package/server/public/flutter_bootstrap.js +1 -1
- package/server/public/main.dart.js +37410 -37351
- package/server/routes/auth.js +2 -1
- package/server/routes/settings.js +24 -24
package/docs/configuration.md
CHANGED
|
@@ -13,6 +13,7 @@ AI provider credentials, OAuth client secrets, and deployment controls are not c
|
|
|
13
13
|
| `SESSION_SECRET` | required | Random string for session signing. Generate one with `openssl rand -hex 32`. |
|
|
14
14
|
| `NODE_ENV` | `production` | Set to `development` to enable verbose logs. |
|
|
15
15
|
| `SECURE_COOKIES` | `false` | Set `true` when NeoAgent is behind a TLS-terminating proxy. |
|
|
16
|
+
| `TRUST_PROXY` | inferred from `PUBLIC_URL`/`SECURE_COOKIES` | Set `true` when NeoAgent runs behind Nginx, Caddy, Cloudflare, Fly, or another reverse proxy that sends `X-Forwarded-*` headers. |
|
|
16
17
|
| `ALLOWED_ORIGINS` | none | Comma-separated CORS origins, for example `https://example.com`. |
|
|
17
18
|
| `NEOAGENT_DEPLOYMENT_MODE` | `self_hosted` | `self_hosted` enables in-app update controls; `managed` hides operator-only controls for SaaS deployments. |
|
|
18
19
|
| `NEOAGENT_RELEASE_CHANNEL` | `stable` | Release track used by the self-hosted updater. |
|
package/lib/manager.js
CHANGED
|
@@ -444,6 +444,8 @@ async function cmdSetup() {
|
|
|
444
444
|
const secureCookiesDefault = current.SECURE_COOKIES ||
|
|
445
445
|
(String(publicUrl || '').trim().startsWith('https://') ? 'true' : 'false');
|
|
446
446
|
const secureCookies = await ask('Secure cookies (true/false)', secureCookiesDefault);
|
|
447
|
+
const trustProxyDefault = current.TRUST_PROXY || secureCookiesDefault;
|
|
448
|
+
const trustProxy = await ask('Trust reverse proxy headers (true/false)', trustProxyDefault);
|
|
447
449
|
const sessionSecret = await askSecret('Session secret', current.SESSION_SECRET || randomSecret());
|
|
448
450
|
const deploymentMode = await ask(
|
|
449
451
|
'Deployment mode (self_hosted/managed)',
|
|
@@ -546,6 +548,7 @@ async function cmdSetup() {
|
|
|
546
548
|
current.TELNYX_WEBHOOK_TOKEN || ''
|
|
547
549
|
);
|
|
548
550
|
const normalizedSecureCookies = String(secureCookies || '').trim().toLowerCase() === 'true' ? 'true' : 'false';
|
|
551
|
+
const normalizedTrustProxy = String(trustProxy || '').trim().toLowerCase() === 'true' ? 'true' : 'false';
|
|
549
552
|
const normalizedDeploymentMode = parseDeploymentMode(deploymentMode);
|
|
550
553
|
const normalizedReleaseChannel = parseReleaseChannel(releaseChannel) || 'stable';
|
|
551
554
|
|
|
@@ -554,6 +557,7 @@ async function cmdSetup() {
|
|
|
554
557
|
`PORT=${port}`,
|
|
555
558
|
publicUrl ? `PUBLIC_URL=${publicUrl}` : '',
|
|
556
559
|
`SECURE_COOKIES=${normalizedSecureCookies}`,
|
|
560
|
+
`TRUST_PROXY=${normalizedTrustProxy}`,
|
|
557
561
|
`SESSION_SECRET=${sessionSecret}`,
|
|
558
562
|
`NEOAGENT_DEPLOYMENT_MODE=${normalizedDeploymentMode}`,
|
|
559
563
|
`NEOAGENT_RELEASE_CHANNEL=${normalizedReleaseChannel}`,
|
package/package.json
CHANGED
|
@@ -98,7 +98,7 @@ function buildHelmetOptions({ secureCookies }) {
|
|
|
98
98
|
};
|
|
99
99
|
}
|
|
100
100
|
|
|
101
|
-
function createSessionMiddleware({ secureCookies }) {
|
|
101
|
+
function createSessionMiddleware({ secureCookies, trustProxy }) {
|
|
102
102
|
return session({
|
|
103
103
|
store: new SQLiteStore({
|
|
104
104
|
client: sessionsDb,
|
|
@@ -109,6 +109,7 @@ function createSessionMiddleware({ secureCookies }) {
|
|
|
109
109
|
}),
|
|
110
110
|
secret: getSessionSecret(),
|
|
111
111
|
name: 'neoagent.sid',
|
|
112
|
+
proxy: trustProxy,
|
|
112
113
|
resave: false,
|
|
113
114
|
saveUninitialized: false,
|
|
114
115
|
cookie: {
|
|
@@ -120,7 +121,7 @@ function createSessionMiddleware({ secureCookies }) {
|
|
|
120
121
|
});
|
|
121
122
|
}
|
|
122
123
|
|
|
123
|
-
function applyHttpMiddleware(app, { secureCookies, sessionMiddleware, validateOrigin }) {
|
|
124
|
+
function applyHttpMiddleware(app, { secureCookies, trustProxy, sessionMiddleware, validateOrigin }) {
|
|
124
125
|
const rawRecordingChunkBody = require('express').raw({ limit: '50mb', type: '*/*' });
|
|
125
126
|
const jsonBody = require('express').json({
|
|
126
127
|
limit: '10mb',
|
|
@@ -147,9 +148,9 @@ function applyHttpMiddleware(app, { secureCookies, sessionMiddleware, validateOr
|
|
|
147
148
|
isRecordingChunkPath(requestPath(req)) ? next() : handler(req, res, next)
|
|
148
149
|
);
|
|
149
150
|
|
|
150
|
-
if (
|
|
151
|
+
if (trustProxy) {
|
|
151
152
|
app.set('trust proxy', 1);
|
|
152
|
-
console.log('[HTTP] trust proxy enabled
|
|
153
|
+
console.log('[HTTP] trust proxy enabled for proxied deployment handling');
|
|
153
154
|
}
|
|
154
155
|
|
|
155
156
|
app.use(helmet(buildHelmetOptions({ secureCookies })));
|
package/server/index.js
CHANGED
|
@@ -35,8 +35,24 @@ const { registerErrorHandler } = require('./http/errors');
|
|
|
35
35
|
const { startServices, stopServices } = require('./services/manager');
|
|
36
36
|
const { bindBrowserExtensionGateway } = require('./services/browser/extension/gateway');
|
|
37
37
|
|
|
38
|
+
function parseBooleanFlag(value, fallback = false) {
|
|
39
|
+
const normalized = String(value || '').trim().toLowerCase();
|
|
40
|
+
if (['1', 'true', 'yes', 'on'].includes(normalized)) return true;
|
|
41
|
+
if (['0', 'false', 'no', 'off'].includes(normalized)) return false;
|
|
42
|
+
return fallback;
|
|
43
|
+
}
|
|
44
|
+
|
|
38
45
|
const PORT = Number(process.env.PORT) || 3333;
|
|
39
|
-
const
|
|
46
|
+
const PUBLIC_URL = String(process.env.PUBLIC_URL || '').trim();
|
|
47
|
+
const PUBLIC_URL_IS_HTTPS = PUBLIC_URL.startsWith('https://');
|
|
48
|
+
const SECURE_COOKIES = parseBooleanFlag(
|
|
49
|
+
process.env.SECURE_COOKIES,
|
|
50
|
+
PUBLIC_URL_IS_HTTPS,
|
|
51
|
+
);
|
|
52
|
+
const TRUST_PROXY = parseBooleanFlag(
|
|
53
|
+
process.env.TRUST_PROXY,
|
|
54
|
+
SECURE_COOKIES || PUBLIC_URL_IS_HTTPS,
|
|
55
|
+
);
|
|
40
56
|
|
|
41
57
|
function logStartupConfig() {
|
|
42
58
|
const flags = {
|
|
@@ -60,6 +76,11 @@ function logStartupConfig() {
|
|
|
60
76
|
console.log(`[Startup] Legacy env fallback: ${LEGACY_ENV_FILE}`);
|
|
61
77
|
}
|
|
62
78
|
console.log('[Startup] Key availability:', flags);
|
|
79
|
+
console.log('[Startup] HTTP runtime:', {
|
|
80
|
+
publicUrl: PUBLIC_URL || null,
|
|
81
|
+
secureCookies: SECURE_COOKIES,
|
|
82
|
+
trustProxy: TRUST_PROXY,
|
|
83
|
+
});
|
|
63
84
|
}
|
|
64
85
|
|
|
65
86
|
logStartupConfig();
|
|
@@ -77,12 +98,21 @@ if (!configuredSessionSecret()) {
|
|
|
77
98
|
const app = express();
|
|
78
99
|
const httpServer = createServer(app);
|
|
79
100
|
const io = createSocketServer(httpServer, { validateOrigin });
|
|
80
|
-
|
|
101
|
+
app.locals.httpRuntimeConfig = {
|
|
102
|
+
secureCookies: SECURE_COOKIES,
|
|
103
|
+
trustProxy: TRUST_PROXY,
|
|
104
|
+
publicUrl: PUBLIC_URL || null,
|
|
105
|
+
};
|
|
106
|
+
const sessionMiddleware = createSessionMiddleware({
|
|
107
|
+
secureCookies: SECURE_COOKIES,
|
|
108
|
+
trustProxy: TRUST_PROXY,
|
|
109
|
+
});
|
|
81
110
|
const activeSockets = new Set();
|
|
82
111
|
|
|
83
112
|
setupConsoleInterceptor(io);
|
|
84
113
|
applyHttpMiddleware(app, {
|
|
85
114
|
secureCookies: SECURE_COOKIES,
|
|
115
|
+
trustProxy: TRUST_PROXY,
|
|
86
116
|
sessionMiddleware,
|
|
87
117
|
validateOrigin
|
|
88
118
|
});
|
|
@@ -37,6 +37,6 @@ _flutter.buildConfig = {"engineRevision":"59aa584fdf100e6c78c785d8a5b565d1de4b48
|
|
|
37
37
|
|
|
38
38
|
_flutter.loader.load({
|
|
39
39
|
serviceWorkerSettings: {
|
|
40
|
-
serviceWorkerVersion: "
|
|
40
|
+
serviceWorkerVersion: "2239132294" /* Flutter's service worker is deprecated and will be removed in a future Flutter release. */
|
|
41
41
|
}
|
|
42
42
|
});
|