agentgui 1.0.794 → 1.0.795

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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/server.js +21 -20
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentgui",
3
- "version": "1.0.794",
3
+ "version": "1.0.795",
4
4
  "description": "Multi-agent ACP client with real-time communication",
5
5
  "type": "module",
6
6
  "main": "electron/main.js",
package/server.js CHANGED
@@ -8,6 +8,7 @@ import { WebSocketServer } from 'ws';
8
8
  import { execSync, spawn } from 'child_process';
9
9
  import { LRUCache } from 'lru-cache';
10
10
  import { createRequire } from 'module';
11
+ import crypto from 'crypto';
11
12
  const PKG_VERSION = JSON.parse(fs.readFileSync(new URL('./package.json', import.meta.url), 'utf8')).version;
12
13
  import express from 'express';
13
14
  import Busboy from 'busboy';
@@ -59,20 +60,7 @@ process.on('unhandledRejection', (reason, promise) => {
59
60
  if (reason instanceof Error) console.error(reason.stack);
60
61
  });
61
62
 
62
- function gracefulShutdown(signal) {
63
- console.log(`[SIGNAL] ${signal} received - graceful shutdown`);
64
- try { pm2Manager.disconnect(); } catch (_) {}
65
- if (jsonlWatcher) try { jsonlWatcher.stop(); } catch (_) {}
66
- for (const [convId, entry] of activeExecutions) {
67
- try { if (entry.pid) process.kill(entry.pid, 'SIGTERM'); } catch (_) {}
68
- }
69
- stopACPTools().catch(() => {}).finally(() => {
70
- try { wss.close(() => server.close(() => process.exit(0))); } catch (_) { process.exit(0); }
71
- setTimeout(() => process.exit(1), 5000);
72
- });
73
- }
74
- process.on('SIGINT', () => gracefulShutdown('SIGINT'));
75
- process.on('SIGTERM', () => gracefulShutdown('SIGTERM'));
63
+ // Signal handlers registered after server initialization (see bottom of file)
76
64
  process.on('SIGHUP', () => { console.log('[SIGNAL] SIGHUP received (ignored - uncrashable)'); });
77
65
  process.on('beforeExit', (code) => { console.log('[PROCESS] beforeExit with code:', code); });
78
66
  process.on('exit', (code) => { console.log('[PROCESS] exit with code:', code); });
@@ -469,7 +457,7 @@ const server = http.createServer(async (req, res) => {
469
457
  try {
470
458
  const _decoded = Buffer.from(_auth.slice(6), 'base64').toString('utf8');
471
459
  const _ci = _decoded.indexOf(':');
472
- if (_ci !== -1) _ok = _decoded.slice(_ci + 1) === _pwd;
460
+ if (_ci !== -1) { const _p = _decoded.slice(_ci + 1); try { _ok = _p.length === _pwd.length && crypto.timingSafeEqual(Buffer.from(_p), Buffer.from(_pwd)); } catch { _ok = false; } }
473
461
  } catch (_) {}
474
462
  }
475
463
  if (!_ok) {
@@ -1966,10 +1954,21 @@ async function processMessageWithStreaming(conversationId, messageId, sessionId,
1966
1954
  }
1967
1955
 
1968
1956
  // Set flag to stop processing and trigger retry
1969
- rateLimitState.set(conversationId, {
1970
- retryAt: Date.now() + (retryAfterSec * 1000),
1971
- cooldownMs: retryAfterSec * 1000,
1972
- retryCount: 0,
1957
+ const existingRetryCount = rateLimitState.get(conversationId)?.retryCount || 0;
1958
+ if (existingRetryCount >= 3) {
1959
+ debugLog(`[rate-limit] Conv ${conversationId} stream rate limit hit ${existingRetryCount + 1} times, giving up`);
1960
+ batcher.drain();
1961
+ activeExecutions.delete(conversationId);
1962
+ queries.setIsStreaming(conversationId, false);
1963
+ const errorMessage = queries.createMessage(conversationId, 'assistant', `Error: Rate limit exceeded after ${existingRetryCount + 1} attempts. Please try again later.`);
1964
+ broadcastSync({ type: 'message_created', conversationId, message: errorMessage, timestamp: Date.now() });
1965
+ broadcastSync({ type: 'streaming_complete', sessionId, conversationId, interrupted: true, timestamp: Date.now() });
1966
+ return;
1967
+ }
1968
+ rateLimitState.set(conversationId, {
1969
+ retryAt: Date.now() + (retryAfterSec * 1000),
1970
+ cooldownMs: retryAfterSec * 1000,
1971
+ retryCount: existingRetryCount + 1,
1973
1972
  isStreamDetected: true
1974
1973
  });
1975
1974
 
@@ -2938,10 +2937,12 @@ function killActiveExecutions() {
2938
2937
 
2939
2938
  process.on('SIGTERM', () => {
2940
2939
  console.log('[SIGNAL] SIGTERM received - graceful shutdown');
2941
- if (!watch) killActiveExecutions();
2940
+ killActiveExecutions();
2941
+ if (jsonlWatcher) try { jsonlWatcher.stop(); } catch (_) {}
2942
2942
  try { pm2Manager.disconnect(); } catch (_) {}
2943
2943
  stopACPTools().catch(() => {}).finally(() => {
2944
2944
  try { wss.close(() => server.close(() => process.exit(0))); } catch (_) { process.exit(0); }
2945
+ setTimeout(() => process.exit(1), 5000);
2945
2946
  });
2946
2947
  });
2947
2948