neoagent 2.0.5 → 2.0.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.
@@ -1,5 +1,6 @@
1
1
  const express = require('express');
2
2
  const fs = require('fs');
3
+ const path = require('path');
3
4
  const router = express.Router();
4
5
  const db = require('../db/database');
5
6
  const { requireAuth } = require('../middleware/auth');
@@ -28,6 +29,17 @@ function readUpdateStatus() {
28
29
  }
29
30
  }
30
31
 
32
+ function writeUpdateStatus(patch) {
33
+ const next = {
34
+ ...readUpdateStatus(),
35
+ ...patch,
36
+ updatedAt: new Date().toISOString()
37
+ };
38
+ fs.mkdirSync(path.dirname(UPDATE_STATUS_FILE), { recursive: true });
39
+ fs.writeFileSync(UPDATE_STATUS_FILE, JSON.stringify(next, null, 2));
40
+ return next;
41
+ }
42
+
31
43
  // Get supported models metadata
32
44
  router.get('/meta/models', async (req, res) => {
33
45
  const { getSupportedModels } = require('../services/ai/models');
@@ -221,6 +233,16 @@ router.post('/update', (req, res) => {
221
233
  return res.status(409).json({ success: false, error: 'An update is already running' });
222
234
  }
223
235
  console.log('[Settings] Triggering update-runner...');
236
+ writeUpdateStatus({
237
+ state: 'running',
238
+ progress: 1,
239
+ phase: 'starting',
240
+ message: 'Launching update job',
241
+ startedAt: new Date().toISOString(),
242
+ completedAt: null,
243
+ changelog: [],
244
+ logs: []
245
+ });
224
246
 
225
247
  // Spawn detached runner so status survives server restarts.
226
248
  const child = spawn(process.execPath, ['scripts/update-runner.js'], {
@@ -229,6 +251,16 @@ router.post('/update', (req, res) => {
229
251
  cwd: APP_DIR
230
252
  });
231
253
 
254
+ child.once('error', (error) => {
255
+ writeUpdateStatus({
256
+ state: 'failed',
257
+ progress: 100,
258
+ phase: 'failed',
259
+ message: `Failed to launch update job: ${error.message}`,
260
+ completedAt: new Date().toISOString()
261
+ });
262
+ });
263
+
232
264
  child.unref();
233
265
  res.json({ success: true, message: 'Update triggered', pid: child.pid });
234
266
  });
@@ -180,8 +180,7 @@ async function isAllowedMessagingSender({ io, userId, msg }) {
180
180
  }
181
181
  }
182
182
 
183
- const enforceEmptyWhitelist = msg.platform === 'whatsapp';
184
- const shouldCheckWhitelist = whitelist.length > 0 || enforceEmptyWhitelist;
183
+ const shouldCheckWhitelist = whitelist.length > 0;
185
184
 
186
185
  if (!shouldCheckWhitelist) {
187
186
  return true;
@@ -196,11 +195,22 @@ async function isAllowedMessagingSender({ io, userId, msg }) {
196
195
  console.log(
197
196
  `[Messaging] Blocked ${msg.platform} message from ${msg.sender} (not in whitelist)`
198
197
  );
198
+ const suggestions = [];
199
+ if (msg.platform === 'whatsapp') {
200
+ const normalizedSender = normalizeWhatsAppId(msg.sender || msg.chatId);
201
+ if (normalizedSender) {
202
+ suggestions.push({
203
+ label: `Add sender (${msg.senderName || normalizedSender})`,
204
+ prefixedId: normalizedSender
205
+ });
206
+ }
207
+ }
199
208
  io.to(`user:${userId}`).emit('messaging:blocked_sender', {
200
209
  platform: msg.platform,
201
210
  sender: msg.sender,
202
211
  chatId: msg.chatId,
203
- senderName: msg.senderName || null
212
+ senderName: msg.senderName || null,
213
+ suggestions: suggestions.length > 0 ? suggestions : null
204
214
  });
205
215
  return false;
206
216
  }
@@ -65,6 +65,30 @@ class DiscordPlatform extends BasePlatform {
65
65
 
66
66
  this._client.once('error', (err) => { clearTimeout(timeout); reject(err); });
67
67
  this._client.on('error', (err) => console.error('[Discord] Client error:', err.message));
68
+ this._client.on('shardDisconnect', (event, shardId) => {
69
+ this.status = 'disconnected';
70
+ console.warn(`[Discord] Shard ${shardId} disconnected (${event?.code || 'unknown'})`);
71
+ this.emit('disconnected', {
72
+ manual: false,
73
+ shardId,
74
+ code: event?.code || null,
75
+ reason: event?.reason || null,
76
+ });
77
+ });
78
+ this._client.on('shardReconnecting', (shardId) => {
79
+ this.status = 'connecting';
80
+ console.log(`[Discord] Shard ${shardId} reconnecting`);
81
+ });
82
+ this._client.on('shardResume', (_replayedEvents, shardId) => {
83
+ this.status = 'connected';
84
+ console.log(`[Discord] Shard ${shardId} resumed`);
85
+ this.emit('connected');
86
+ });
87
+ this._client.on('invalidated', () => {
88
+ this.status = 'logged_out';
89
+ console.warn('[Discord] Session invalidated');
90
+ this.emit('logged_out');
91
+ });
68
92
  this._client.on('messageCreate', (msg) => this._handleMessage(msg));
69
93
 
70
94
  this._client.login(this.token).catch((err) => { clearTimeout(timeout); reject(err); });
@@ -88,8 +112,11 @@ class DiscordPlatform extends BasePlatform {
88
112
 
89
113
  /** Returns {allowed, requireMention} */
90
114
  _checkAccess(message) {
91
- // Empty whitelist: block everyone (add via the allow popup)
92
- if (this.allowedEntries.size === 0) return { allowed: false, requireMention: false };
115
+ // Default behavior with no allow-list: respond in DMs and require a mention in guilds.
116
+ if (this.allowedEntries.size === 0) {
117
+ const isDM = message.channel.type === ChannelType.DM;
118
+ return { allowed: true, requireMention: !isDM };
119
+ }
93
120
 
94
121
  // Check prefixed entries
95
122
  const userId = message.author.id;
@@ -86,8 +86,10 @@ class TelegramPlatform extends BasePlatform {
86
86
  _checkAccess(msg) {
87
87
  const userId = String(msg.from.id);
88
88
  const chatId = String(msg.chat.id); // negative for groups
89
+ const isPrivate = msg.chat.type === 'private';
89
90
 
90
- if (this.allowedEntries.size === 0) return { allowed: false, requireMention: false };
91
+ // Default behavior with no allow-list: respond in private chats and require @mention in groups.
92
+ if (this.allowedEntries.size === 0) return { allowed: true, requireMention: !isPrivate };
91
93
 
92
94
  if (super._checkAccess(`user:${userId}`)) return { allowed: true, requireMention: false };
93
95
  if (super._checkAccess(userId)) return { allowed: true, requireMention: false }; // legacy