agentgui 1.0.794 → 1.0.796
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 +1 -1
- package/server.js +41 -29
package/package.json
CHANGED
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
|
-
|
|
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)
|
|
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.
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
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
|
|
|
@@ -2073,27 +2072,38 @@ async function processMessageWithStreaming(conversationId, messageId, sessionId,
|
|
|
2073
2072
|
} catch (e) {}
|
|
2074
2073
|
}
|
|
2075
2074
|
|
|
2076
|
-
rateLimitState.
|
|
2077
|
-
|
|
2078
|
-
|
|
2079
|
-
|
|
2075
|
+
const existingRetryCount2 = rateLimitState.get(conversationId)?.retryCount || 0;
|
|
2076
|
+
if (existingRetryCount2 >= 3) {
|
|
2077
|
+
debugLog(`[rate-limit] Conv ${conversationId} result rate limit hit ${existingRetryCount2 + 1} times, giving up`);
|
|
2078
|
+
batcher.drain();
|
|
2079
|
+
activeExecutions.delete(conversationId);
|
|
2080
|
+
queries.setIsStreaming(conversationId, false);
|
|
2081
|
+
const errorMessage = queries.createMessage(conversationId, 'assistant', `Error: Rate limit exceeded after ${existingRetryCount2 + 1} attempts. Please try again later.`);
|
|
2082
|
+
broadcastSync({ type: 'message_created', conversationId, message: errorMessage, timestamp: Date.now() });
|
|
2083
|
+
broadcastSync({ type: 'streaming_complete', sessionId, conversationId, interrupted: true, timestamp: Date.now() });
|
|
2084
|
+
return;
|
|
2085
|
+
}
|
|
2086
|
+
rateLimitState.set(conversationId, {
|
|
2087
|
+
retryAt: Date.now() + (retryAfterSec * 1000),
|
|
2088
|
+
cooldownMs: retryAfterSec * 1000,
|
|
2089
|
+
retryCount: existingRetryCount2 + 1,
|
|
2080
2090
|
isStreamDetected: true
|
|
2081
2091
|
});
|
|
2082
|
-
|
|
2092
|
+
|
|
2083
2093
|
broadcastSync({
|
|
2084
2094
|
type: 'rate_limit_hit',
|
|
2085
2095
|
sessionId,
|
|
2086
2096
|
conversationId,
|
|
2087
2097
|
retryAfterMs: retryAfterSec * 1000,
|
|
2088
2098
|
retryAt: Date.now() + (retryAfterSec * 1000),
|
|
2089
|
-
retryCount: 1,
|
|
2099
|
+
retryCount: existingRetryCount2 + 1,
|
|
2090
2100
|
timestamp: Date.now()
|
|
2091
2101
|
});
|
|
2092
|
-
|
|
2102
|
+
|
|
2093
2103
|
batcher.drain();
|
|
2094
2104
|
activeExecutions.delete(conversationId);
|
|
2095
2105
|
queries.setIsStreaming(conversationId, false);
|
|
2096
|
-
|
|
2106
|
+
|
|
2097
2107
|
setTimeout(() => {
|
|
2098
2108
|
rateLimitState.delete(conversationId);
|
|
2099
2109
|
broadcastSync({
|
|
@@ -2103,7 +2113,7 @@ async function processMessageWithStreaming(conversationId, messageId, sessionId,
|
|
|
2103
2113
|
});
|
|
2104
2114
|
scheduleRetry(conversationId, messageId, content, agentId, model, subAgent);
|
|
2105
2115
|
}, retryAfterSec * 1000);
|
|
2106
|
-
|
|
2116
|
+
|
|
2107
2117
|
return;
|
|
2108
2118
|
}
|
|
2109
2119
|
|
|
@@ -2938,10 +2948,12 @@ function killActiveExecutions() {
|
|
|
2938
2948
|
|
|
2939
2949
|
process.on('SIGTERM', () => {
|
|
2940
2950
|
console.log('[SIGNAL] SIGTERM received - graceful shutdown');
|
|
2941
|
-
|
|
2951
|
+
killActiveExecutions();
|
|
2952
|
+
if (jsonlWatcher) try { jsonlWatcher.stop(); } catch (_) {}
|
|
2942
2953
|
try { pm2Manager.disconnect(); } catch (_) {}
|
|
2943
2954
|
stopACPTools().catch(() => {}).finally(() => {
|
|
2944
2955
|
try { wss.close(() => server.close(() => process.exit(0))); } catch (_) { process.exit(0); }
|
|
2956
|
+
setTimeout(() => process.exit(1), 5000);
|
|
2945
2957
|
});
|
|
2946
2958
|
});
|
|
2947
2959
|
|