neoagent 2.3.1-beta.5 → 2.3.1-beta.7
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 +13 -0
- package/docs/configuration.md +8 -4
- package/docs/integrations.md +1 -1
- package/package.json +3 -1
- package/server/db/database.js +11 -0
- package/server/http/middleware.js +50 -0
- package/server/index.js +1 -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 +50245 -49865
- package/server/routes/integrations.js +86 -0
- package/server/routes/memory.js +11 -2
- package/server/{http/routes → routes}/screenHistory.js +2 -2
- package/server/{http/routes → routes}/triggers.js +2 -2
- package/server/services/ai/models.js +37 -1
- package/server/services/ai/providers/codex.js +244 -0
- package/server/services/ai/providers/copilot.js +457 -0
- package/server/services/ai/settings.js +20 -0
- package/server/services/integrations/codex/provider.js +281 -0
- package/server/services/integrations/env.js +5 -0
- package/server/services/integrations/github/common.js +106 -0
- package/server/services/integrations/github/provider.js +499 -0
- package/server/services/integrations/github/repos.js +1124 -0
- package/server/services/integrations/home_assistant/provider.js +306 -26
- package/server/services/integrations/manager.js +63 -7
- package/server/services/integrations/oauth_provider.js +13 -6
- package/server/services/integrations/provider_config_store.js +76 -0
- package/server/services/integrations/registry.js +4 -0
- package/server/services/memory/manager.js +39 -2
- package/server/services/voice/openaiClient.js +4 -1
- package/server/services/voice/providers.js +2 -1
- package/server/utils/local_secrets.js +56 -0
- package/server/utils/logger.js +37 -9
package/.env.example
CHANGED
|
@@ -6,6 +6,10 @@ PORT=3333
|
|
|
6
6
|
NODE_ENV=production
|
|
7
7
|
SESSION_SECRET=change-this-to-a-random-secret-in-production
|
|
8
8
|
|
|
9
|
+
# Optional: dedicated key for encrypting local at-rest secrets (for example API_KEYS.json).
|
|
10
|
+
# If unset, encryption falls back to SESSION_SECRET.
|
|
11
|
+
# NEOAGENT_DATA_ENCRYPTION_KEY=
|
|
12
|
+
|
|
9
13
|
# Public base URL used for OAuth callbacks and external links.
|
|
10
14
|
# Example: https://agent.example.com
|
|
11
15
|
PUBLIC_URL=
|
|
@@ -139,6 +143,15 @@ FIGMA_OAUTH_CLIENT_ID=your-figma-oauth-client-id
|
|
|
139
143
|
FIGMA_OAUTH_CLIENT_SECRET=your-figma-oauth-client-secret
|
|
140
144
|
FIGMA_OAUTH_REDIRECT_URI=
|
|
141
145
|
|
|
146
|
+
# GitHub official integration OAuth client.
|
|
147
|
+
# Redirect URI should match <PUBLIC_URL>/api/integrations/oauth/callback.
|
|
148
|
+
# Prefer least-privilege OAuth scopes for your use case.
|
|
149
|
+
# Read-oriented examples: public_repo (public repositories), repo:status (commit status), read:org (org membership).
|
|
150
|
+
# Avoid broad blanket scopes unless explicitly required by a specific write workflow.
|
|
151
|
+
GITHUB_OAUTH_CLIENT_ID=your-github-oauth-client-id
|
|
152
|
+
GITHUB_OAUTH_CLIENT_SECRET=your-github-oauth-client-secret
|
|
153
|
+
GITHUB_OAUTH_REDIRECT_URI=
|
|
154
|
+
|
|
142
155
|
########################################
|
|
143
156
|
# Tools and media services
|
|
144
157
|
########################################
|
package/docs/configuration.md
CHANGED
|
@@ -90,14 +90,18 @@ All OAuth callbacks default to `PUBLIC_URL + /api/integrations/oauth/callback` u
|
|
|
90
90
|
| `FIGMA_OAUTH_CLIENT_ID` | Figma OAuth client ID |
|
|
91
91
|
| `FIGMA_OAUTH_CLIENT_SECRET` | Figma OAuth client secret |
|
|
92
92
|
| `FIGMA_OAUTH_REDIRECT_URI` | Optional Figma OAuth callback URL |
|
|
93
|
-
| `HOME_ASSISTANT_BASE_URL` | Home Assistant base URL
|
|
94
|
-
| `HOME_ASSISTANT_OAUTH_CLIENT_ID` | Home Assistant OAuth client ID |
|
|
95
|
-
| `HOME_ASSISTANT_OAUTH_CLIENT_SECRET` | Home Assistant OAuth client secret |
|
|
96
|
-
| `HOME_ASSISTANT_OAUTH_REDIRECT_URI` | Optional Home Assistant OAuth callback URL |
|
|
93
|
+
| `HOME_ASSISTANT_BASE_URL` | Optional fallback Home Assistant base URL. Users can configure this per account in Official Integrations. |
|
|
94
|
+
| `HOME_ASSISTANT_OAUTH_CLIENT_ID` | Optional fallback Home Assistant OAuth client ID. |
|
|
95
|
+
| `HOME_ASSISTANT_OAUTH_CLIENT_SECRET` | Optional fallback Home Assistant OAuth client secret. |
|
|
96
|
+
| `HOME_ASSISTANT_OAUTH_REDIRECT_URI` | Optional fallback Home Assistant OAuth callback URL. |
|
|
97
|
+
| `HOME_ASSISTANT_ALLOW_PRIVATE_BASE_URL` | Optional safety override. Set to `1` only if you intentionally allow Home Assistant base URLs on localhost/private networks. |
|
|
97
98
|
| `SPOTIFY_OAUTH_CLIENT_ID` | Spotify OAuth client ID |
|
|
98
99
|
| `SPOTIFY_OAUTH_CLIENT_SECRET` | Spotify OAuth client secret |
|
|
99
100
|
| `SPOTIFY_OAUTH_REDIRECT_URI` | Optional Spotify OAuth callback URL |
|
|
100
101
|
|
|
102
|
+
Home Assistant no longer requires server-side setup. Each user can open Official Integrations, select Home Assistant, and enter their own base URL and OAuth app credentials.
|
|
103
|
+
For safety, local/private Home Assistant targets are blocked by default unless `HOME_ASSISTANT_ALLOW_PRIVATE_BASE_URL=1` is set on the server.
|
|
104
|
+
|
|
101
105
|
Weather integration uses Open-Meteo public endpoints and does not require OAuth environment variables.
|
|
102
106
|
|
|
103
107
|
## Messaging
|
package/docs/integrations.md
CHANGED
|
@@ -17,7 +17,7 @@ The built-in registry includes:
|
|
|
17
17
|
| Weather | Keyless Open-Meteo current weather and forecast tools |
|
|
18
18
|
| Spotify | Playback state, recently played, search, and playback controls |
|
|
19
19
|
|
|
20
|
-
OAuth app credentials are configured through server environment variables. Account connections are created in the Flutter UI under **Integrations**. Connected tools are exposed to the agent as structured tools, so prefer them over browser automation when they can do the job.
|
|
20
|
+
OAuth app credentials are configured through server environment variables for most providers. Home Assistant can also be configured per-user in the Flutter **Integrations** UI without any server-side setup. Account connections are created in the Flutter UI under **Integrations**. Connected tools are exposed to the agent as structured tools, so prefer them over browser automation when they can do the job.
|
|
21
21
|
|
|
22
22
|
Weather note: the Weather integration uses Open-Meteo public APIs and does not require OAuth client credentials.
|
|
23
23
|
|
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.7",
|
|
4
4
|
"description": "Proactive personal AI agent with no limits",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"main": "server/index.js",
|
|
@@ -51,6 +51,7 @@
|
|
|
51
51
|
"homepage": "https://github.com/NeoLabs-Systems/NeoAgent#readme",
|
|
52
52
|
"dependencies": {
|
|
53
53
|
"@anthropic-ai/sdk": "^0.39.0",
|
|
54
|
+
"@github/copilot-sdk": "^0.3.0",
|
|
54
55
|
"@google/generative-ai": "^0.24.0",
|
|
55
56
|
"@modelcontextprotocol/sdk": "^1.12.1",
|
|
56
57
|
"baileys": "^6.7.21",
|
|
@@ -66,6 +67,7 @@
|
|
|
66
67
|
"geoip-lite": "^1.4.10",
|
|
67
68
|
"googleapis": "^150.0.1",
|
|
68
69
|
"helmet": "^8.0.0",
|
|
70
|
+
"ipaddr.js": "^2.3.0",
|
|
69
71
|
"multer": "^1.4.5-lts.1",
|
|
70
72
|
"node-cron": "^3.0.3",
|
|
71
73
|
"node-pty": "^1.0.0",
|
package/server/db/database.js
CHANGED
|
@@ -272,6 +272,17 @@ db.exec(`
|
|
|
272
272
|
FOREIGN KEY (agent_id) REFERENCES agents(id) ON DELETE SET NULL
|
|
273
273
|
);
|
|
274
274
|
|
|
275
|
+
CREATE TABLE IF NOT EXISTS integration_provider_configs (
|
|
276
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
277
|
+
user_id INTEGER NOT NULL,
|
|
278
|
+
provider_key TEXT NOT NULL,
|
|
279
|
+
config_json TEXT DEFAULT '{}',
|
|
280
|
+
created_at TEXT DEFAULT (datetime('now')),
|
|
281
|
+
updated_at TEXT DEFAULT (datetime('now')),
|
|
282
|
+
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
|
|
283
|
+
UNIQUE(user_id, provider_key)
|
|
284
|
+
);
|
|
285
|
+
|
|
275
286
|
CREATE TABLE IF NOT EXISTS browser_extension_pairing_requests (
|
|
276
287
|
id TEXT PRIMARY KEY,
|
|
277
288
|
user_id INTEGER,
|
|
@@ -88,7 +88,18 @@ function buildHelmetOptions({ secureCookies }) {
|
|
|
88
88
|
return {
|
|
89
89
|
strictTransportSecurity: false,
|
|
90
90
|
crossOriginOpenerPolicy: false,
|
|
91
|
+
crossOriginResourcePolicy: { policy: 'same-site' },
|
|
91
92
|
originAgentCluster: false,
|
|
93
|
+
referrerPolicy: { policy: 'strict-origin-when-cross-origin' },
|
|
94
|
+
permissionsPolicy: {
|
|
95
|
+
features: {
|
|
96
|
+
camera: ['self'],
|
|
97
|
+
geolocation: ['self'],
|
|
98
|
+
microphone: ['self'],
|
|
99
|
+
payment: [],
|
|
100
|
+
usb: [],
|
|
101
|
+
},
|
|
102
|
+
},
|
|
92
103
|
contentSecurityPolicy: {
|
|
93
104
|
directives: {
|
|
94
105
|
defaultSrc: ["'self'"],
|
|
@@ -154,6 +165,16 @@ function applyHttpMiddleware(app, { secureCookies, trustProxy, sessionMiddleware
|
|
|
154
165
|
const path = `${value}`.split('?')[0];
|
|
155
166
|
return path === '/socket.io/' || path === '/socket.io' || path.startsWith('/socket.io/');
|
|
156
167
|
};
|
|
168
|
+
const isStateChangingMethod = (method = '') => ['POST', 'PUT', 'PATCH', 'DELETE'].includes(String(method).toUpperCase());
|
|
169
|
+
const extractOriginFromReferer = (referer = '') => {
|
|
170
|
+
const value = String(referer || '').trim();
|
|
171
|
+
if (!value) return '';
|
|
172
|
+
try {
|
|
173
|
+
return new URL(value).origin;
|
|
174
|
+
} catch {
|
|
175
|
+
return '';
|
|
176
|
+
}
|
|
177
|
+
};
|
|
157
178
|
const requestPath = (req) => req.originalUrl || req.url || req.path || '';
|
|
158
179
|
const applyOnlyToRecordingChunk = (handler) => (req, res, next) => (
|
|
159
180
|
isRecordingChunkPath(requestPath(req)) ? handler(req, res, next) : next()
|
|
@@ -187,6 +208,35 @@ function applyHttpMiddleware(app, { secureCookies, trustProxy, sessionMiddleware
|
|
|
187
208
|
});
|
|
188
209
|
})
|
|
189
210
|
);
|
|
211
|
+
app.use((req, res, next) => {
|
|
212
|
+
const path = `${req.originalUrl || req.url || req.path || ''}`.split('?')[0];
|
|
213
|
+
if (path.startsWith('/api/')) {
|
|
214
|
+
res.setHeader('Cache-Control', 'no-store, max-age=0');
|
|
215
|
+
res.setHeader('Pragma', 'no-cache');
|
|
216
|
+
res.setHeader('Expires', '0');
|
|
217
|
+
}
|
|
218
|
+
next();
|
|
219
|
+
});
|
|
220
|
+
app.use((req, res, next) => {
|
|
221
|
+
const path = `${req.originalUrl || req.url || req.path || ''}`.split('?')[0];
|
|
222
|
+
if (!path.startsWith('/api/')) return next();
|
|
223
|
+
if (!isStateChangingMethod(req.method)) return next();
|
|
224
|
+
|
|
225
|
+
const origin = String(req.get('origin') || '').trim() || extractOriginFromReferer(req.get('referer'));
|
|
226
|
+
if (!origin) return next();
|
|
227
|
+
|
|
228
|
+
const allowBrowserExtensionOrigin = isBrowserExtensionCorsPath(path);
|
|
229
|
+
return validateOrigin(origin, (error) => {
|
|
230
|
+
if (error) {
|
|
231
|
+
logRequestSummary('warn', req, 'blocked state-changing request due to invalid origin', { origin });
|
|
232
|
+
return res.status(403).json({ error: 'Origin not allowed' });
|
|
233
|
+
}
|
|
234
|
+
return next();
|
|
235
|
+
}, {
|
|
236
|
+
allowChromeExtension: allowBrowserExtensionOrigin,
|
|
237
|
+
allowMissingOrigin: false,
|
|
238
|
+
});
|
|
239
|
+
});
|
|
190
240
|
app.use((req, res, next) => {
|
|
191
241
|
const startedAt = Date.now();
|
|
192
242
|
|
package/server/index.js
CHANGED
|
Binary file
|
|
@@ -37,6 +37,6 @@ _flutter.buildConfig = {"engineRevision":"59aa584fdf100e6c78c785d8a5b565d1de4b48
|
|
|
37
37
|
|
|
38
38
|
_flutter.loader.load({
|
|
39
39
|
serviceWorkerSettings: {
|
|
40
|
-
serviceWorkerVersion: "
|
|
40
|
+
serviceWorkerVersion: "1495797212" /* Flutter's service worker is deprecated and will be removed in a future Flutter release. */
|
|
41
41
|
}
|
|
42
42
|
});
|