neoagent 2.1.18-beta.6 → 2.1.18-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 CHANGED
@@ -69,7 +69,8 @@ MINIMAX_API_KEY=your-minimax-api-key-here
69
69
  ########################################
70
70
 
71
71
  # Google Workspace official integration OAuth client.
72
- # Redirect URI should match ${PUBLIC_URL:-http://localhost:3333}/api/integrations/oauth/callback
72
+ # Redirect URI should match <PUBLIC_URL>/api/integrations/oauth/callback.
73
+ # Set PUBLIC_URL to your app's public base URL. Local default is http://localhost:3333.
73
74
  GOOGLE_OAUTH_CLIENT_ID=your-google-oauth-client-id
74
75
  GOOGLE_OAUTH_CLIENT_SECRET=your-google-oauth-client-secret
75
76
  GOOGLE_OAUTH_REDIRECT_URI=
@@ -42,6 +42,8 @@ At least one hosted-provider API key is required unless you only use local Ollam
42
42
  | `DEEPGRAM_LANGUAGE` | Deepgram language override (defaults to `multi`) |
43
43
  | `OLLAMA_URL` | Local Ollama (`http://localhost:11434`) |
44
44
 
45
+ `GOOGLE_OAUTH_CLIENT_SECRET` is sensitive, just like `SESSION_SECRET`. Do not commit it to version control, print it to logs, or expose it in client-side code. Store it in server-side environment variables or a secrets manager, restrict access to operators who need it, and rotate it immediately if you suspect it was exposed.
46
+
45
47
  ### Messaging
46
48
 
47
49
  | Variable | Description |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "neoagent",
3
- "version": "2.1.18-beta.6",
3
+ "version": "2.1.18-beta.7",
4
4
  "description": "Proactive personal AI agent with no limits",
5
5
  "license": "MIT",
6
6
  "main": "server/index.js",
@@ -1,6 +1,10 @@
1
1
  const Database = require('better-sqlite3');
2
2
  const path = require('path');
3
3
  const { DATA_DIR, ensureRuntimeDirs } = require('../../runtime/paths');
4
+ const {
5
+ encryptValue,
6
+ isEncryptedValue,
7
+ } = require('../services/integrations/secrets');
4
8
  ensureRuntimeDirs();
5
9
 
6
10
  const DB_PATH = path.join(DATA_DIR, 'neoagent.db');
@@ -204,6 +208,7 @@ db.exec(`
204
208
  CREATE INDEX IF NOT EXISTS idx_agent_steps_run ON agent_steps(run_id, step_index);
205
209
  CREATE INDEX IF NOT EXISTS idx_integration_connections_user ON integration_connections(user_id, provider_key, app_key);
206
210
  CREATE INDEX IF NOT EXISTS idx_integration_oauth_states_state ON integration_oauth_states(state);
211
+ CREATE INDEX IF NOT EXISTS idx_integration_oauth_states_expires ON integration_oauth_states(expires_at);
207
212
  CREATE INDEX IF NOT EXISTS idx_messages_user ON messages(user_id, created_at DESC);
208
213
  CREATE INDEX IF NOT EXISTS idx_messages_platform ON messages(platform, platform_chat_id);
209
214
  CREATE INDEX IF NOT EXISTS idx_conv_messages ON conversation_messages(conversation_id, created_at);
@@ -379,6 +384,12 @@ db.exec(`
379
384
  CREATE INDEX IF NOT EXISTS idx_recording_sources_session ON recording_sources(session_id, source_key);
380
385
  CREATE INDEX IF NOT EXISTS idx_recording_chunks_source ON recording_chunks(source_id, sequence_index);
381
386
  CREATE INDEX IF NOT EXISTS idx_recording_segments_session ON recording_transcript_segments(session_id, start_ms, created_at);
387
+
388
+ CREATE TRIGGER IF NOT EXISTS cleanup_expired_oauth_states
389
+ AFTER INSERT ON integration_oauth_states BEGIN
390
+ DELETE FROM integration_oauth_states
391
+ WHERE datetime(expires_at) <= datetime('now');
392
+ END;
382
393
  `);
383
394
 
384
395
  try {
@@ -581,8 +592,43 @@ function migrateIntegrationOauthStatesTable() {
581
592
  `);
582
593
  }
583
594
 
595
+ function migrateIntegrationSecretStorage() {
596
+ try {
597
+ const connectionRows = db
598
+ .prepare('SELECT id, credentials_json FROM integration_connections')
599
+ .all();
600
+ const updateConnection = db.prepare(
601
+ 'UPDATE integration_connections SET credentials_json = ? WHERE id = ?',
602
+ );
603
+ for (const row of connectionRows) {
604
+ const current = String(row.credentials_json || '');
605
+ if (!current || isEncryptedValue(current)) continue;
606
+ updateConnection.run(encryptValue(current), row.id);
607
+ }
608
+ } catch {
609
+ // Preserve startup even if a row cannot be re-encrypted.
610
+ }
611
+
612
+ try {
613
+ const stateRows = db
614
+ .prepare('SELECT id, code_verifier FROM integration_oauth_states')
615
+ .all();
616
+ const updateState = db.prepare(
617
+ 'UPDATE integration_oauth_states SET code_verifier = ? WHERE id = ?',
618
+ );
619
+ for (const row of stateRows) {
620
+ const current = String(row.code_verifier || '');
621
+ if (!current || isEncryptedValue(current)) continue;
622
+ updateState.run(encryptValue(current), row.id);
623
+ }
624
+ } catch {
625
+ // Preserve startup even if a row cannot be re-encrypted.
626
+ }
627
+ }
628
+
584
629
  migrateIntegrationConnectionsTable();
585
630
  migrateIntegrationOauthStatesTable();
631
+ migrateIntegrationSecretStorage();
586
632
 
587
633
  try {
588
634
  db.exec(`
@@ -37,6 +37,6 @@ _flutter.buildConfig = {"engineRevision":"425cfb54d01a9472b3e81d9e76fd63a4a44cfb
37
37
 
38
38
  _flutter.loader.load({
39
39
  serviceWorkerSettings: {
40
- serviceWorkerVersion: "3090900279" /* Flutter's service worker is deprecated and will be removed in a future Flutter release. */
40
+ serviceWorkerVersion: "1552279196" /* Flutter's service worker is deprecated and will be removed in a future Flutter release. */
41
41
  }
42
42
  });