neoagent 2.1.18-beta.92 → 2.1.18-beta.93

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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "neoagent",
3
- "version": "2.1.18-beta.92",
3
+ "version": "2.1.18-beta.93",
4
4
  "description": "Proactive personal AI agent with no limits",
5
5
  "license": "MIT",
6
6
  "main": "server/index.js",
@@ -37,6 +37,6 @@ _flutter.buildConfig = {"engineRevision":"59aa584fdf100e6c78c785d8a5b565d1de4b48
37
37
 
38
38
  _flutter.loader.load({
39
39
  serviceWorkerSettings: {
40
- serviceWorkerVersion: "2746919848" /* Flutter's service worker is deprecated and will be removed in a future Flutter release. */
40
+ serviceWorkerVersion: "4149814514" /* Flutter's service worker is deprecated and will be removed in a future Flutter release. */
41
41
  }
42
42
  });
@@ -18,6 +18,7 @@ class TelegramPlatform extends BasePlatform {
18
18
  this._botUser = null;
19
19
  this._contextBuffers = new Map();
20
20
  this._contextMaxSize = 25;
21
+ this._contextMaxChats = 200;
21
22
  }
22
23
 
23
24
  async connect() {
@@ -89,6 +90,7 @@ class TelegramPlatform extends BasePlatform {
89
90
  }
90
91
  this.status = 'disconnected';
91
92
  this._botUser = null;
93
+ this._contextBuffers.clear();
92
94
  this.emit('disconnected', { manual: true });
93
95
  }
94
96
 
@@ -158,6 +160,16 @@ class TelegramPlatform extends BasePlatform {
158
160
  const buf = this._contextBuffers.get(rawChatId);
159
161
  buf.push(entry);
160
162
  if (buf.length > this._contextMaxSize) buf.shift();
163
+
164
+ // Keep only the most recently active chat contexts so memory usage does not
165
+ // grow forever as the bot encounters new chats/groups over time.
166
+ this._contextBuffers.delete(rawChatId);
167
+ this._contextBuffers.set(rawChatId, buf);
168
+ while (this._contextBuffers.size > this._contextMaxChats) {
169
+ const oldestKey = this._contextBuffers.keys().next().value;
170
+ if (oldestKey == null) break;
171
+ this._contextBuffers.delete(oldestKey);
172
+ }
161
173
  }
162
174
 
163
175
  _getContext(rawChatId) {
@@ -49,11 +49,17 @@ class BufferedLiveRelayAdapter {
49
49
  if (!audioBytes.length) {
50
50
  return '';
51
51
  }
52
- return this._transcribeAudioSnapshot(audioBytes, session.inputMimeType, {
53
- model: session.voiceSettings?.liveSttModel,
54
- userId: session.userId,
55
- agentId: session.agentId,
56
- });
52
+ try {
53
+ return await this._transcribeAudioSnapshot(audioBytes, session.inputMimeType, {
54
+ model: session.voiceSettings?.liveSttModel,
55
+ userId: session.userId,
56
+ agentId: session.agentId,
57
+ });
58
+ } finally {
59
+ // Release buffered audio immediately after commit so completed turns do
60
+ // not retain large input chunks until the next turn or explicit close.
61
+ session.resetInput(session.inputMimeType);
62
+ }
57
63
  }
58
64
 
59
65
  _schedulePartialTranscript(session) {
@@ -485,12 +485,16 @@ function setupWebSocket(io, services) {
485
485
  const data = asObject(raw);
486
486
  const agentId = resolveAgentFromPayload(userId, data);
487
487
  const sessionId = toOptionalString(data?.sessionId, 128);
488
- await voiceRuntimeManager.openFlutterSession({
488
+ const session = await voiceRuntimeManager.openFlutterSession({
489
489
  userId,
490
490
  agentId,
491
491
  socket,
492
492
  sessionId: sessionId || null,
493
493
  });
494
+ if (!socket.data.voiceSessionIds) {
495
+ socket.data.voiceSessionIds = new Set();
496
+ }
497
+ socket.data.voiceSessionIds.add(session.id);
494
498
  } catch (err) {
495
499
  socket.emit('voice:error', { error: sanitizeError(err) });
496
500
  }
@@ -665,6 +669,7 @@ function setupWebSocket(io, services) {
665
669
  return socket.emit('voice:error', { error: 'sessionId is required' });
666
670
  }
667
671
  await voiceRuntimeManager.closeSession(sessionId, 'client_closed');
672
+ socket.data.voiceSessionIds?.delete(sessionId);
668
673
  } catch (err) {
669
674
  console.error(`[WS] voice:session_close failed for user ${userId}:`, err);
670
675
  socket.emit('voice:error', {
@@ -802,6 +807,13 @@ function setupWebSocket(io, services) {
802
807
  // ── Disconnect ──
803
808
 
804
809
  socket.on('disconnect', () => {
810
+ const activeVoiceSessionIds = Array.from(socket.data.voiceSessionIds || []);
811
+ for (const sessionId of activeVoiceSessionIds) {
812
+ void voiceRuntimeManager.closeSession(sessionId, 'socket_disconnected').catch((err) => {
813
+ console.error(`[WS] Failed to close voice session ${sessionId} after socket disconnect:`, err);
814
+ });
815
+ }
816
+ socket.data.voiceSessionIds?.clear?.();
805
817
  console.log(`[WS] User ${userId} disconnected (${socket.id})`);
806
818
  });
807
819
  });