@loxia-labs/loxia-autopilot-one 1.0.1 → 1.0.3
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/README.md +44 -54
- package/bin/cli.js +1 -115
- package/bin/loxia-terminal-v2.js +3 -0
- package/bin/loxia-terminal.js +3 -0
- package/bin/start-with-terminal.js +3 -0
- package/package.json +14 -15
- package/scripts/install-scanners.js +1 -235
- package/src/analyzers/CSSAnalyzer.js +1 -297
- package/src/analyzers/ConfigValidator.js +1 -690
- package/src/analyzers/ESLintAnalyzer.js +1 -320
- package/src/analyzers/JavaScriptAnalyzer.js +1 -261
- package/src/analyzers/PrettierFormatter.js +1 -247
- package/src/analyzers/PythonAnalyzer.js +1 -266
- package/src/analyzers/SecurityAnalyzer.js +1 -729
- package/src/analyzers/TypeScriptAnalyzer.js +1 -247
- package/src/analyzers/codeCloneDetector/analyzer.js +1 -344
- package/src/analyzers/codeCloneDetector/detector.js +1 -203
- package/src/analyzers/codeCloneDetector/index.js +1 -160
- package/src/analyzers/codeCloneDetector/parser.js +1 -199
- package/src/analyzers/codeCloneDetector/reporter.js +1 -148
- package/src/analyzers/codeCloneDetector/scanner.js +1 -59
- package/src/core/agentPool.js +1 -1474
- package/src/core/agentScheduler.js +1 -2147
- package/src/core/contextManager.js +1 -709
- package/src/core/messageProcessor.js +1 -732
- package/src/core/orchestrator.js +1 -548
- package/src/core/stateManager.js +1 -877
- package/src/index.js +1 -631
- package/src/interfaces/cli.js +1 -549
- package/src/interfaces/terminal/__tests__/smoke/advancedFeatures.test.js +1 -0
- package/src/interfaces/terminal/__tests__/smoke/agentControl.test.js +1 -0
- package/src/interfaces/terminal/__tests__/smoke/agents.test.js +1 -0
- package/src/interfaces/terminal/__tests__/smoke/components.test.js +1 -0
- package/src/interfaces/terminal/__tests__/smoke/connection.test.js +1 -0
- package/src/interfaces/terminal/__tests__/smoke/enhancements.test.js +1 -0
- package/src/interfaces/terminal/__tests__/smoke/imports.test.js +1 -0
- package/src/interfaces/terminal/__tests__/smoke/messages.test.js +1 -0
- package/src/interfaces/terminal/__tests__/smoke/tools.test.js +1 -0
- package/src/interfaces/terminal/api/apiClient.js +1 -0
- package/src/interfaces/terminal/api/messageRouter.js +1 -0
- package/src/interfaces/terminal/api/session.js +1 -0
- package/src/interfaces/terminal/api/websocket.js +1 -0
- package/src/interfaces/terminal/components/AgentCreator.js +1 -0
- package/src/interfaces/terminal/components/AgentEditor.js +1 -0
- package/src/interfaces/terminal/components/AgentSwitcher.js +1 -0
- package/src/interfaces/terminal/components/ErrorBoundary.js +1 -0
- package/src/interfaces/terminal/components/ErrorPanel.js +1 -0
- package/src/interfaces/terminal/components/Header.js +1 -0
- package/src/interfaces/terminal/components/HelpPanel.js +1 -0
- package/src/interfaces/terminal/components/InputBox.js +1 -0
- package/src/interfaces/terminal/components/Layout.js +1 -0
- package/src/interfaces/terminal/components/LoadingSpinner.js +1 -0
- package/src/interfaces/terminal/components/MessageList.js +1 -0
- package/src/interfaces/terminal/components/MultilineTextInput.js +1 -0
- package/src/interfaces/terminal/components/SearchPanel.js +1 -0
- package/src/interfaces/terminal/components/SettingsPanel.js +1 -0
- package/src/interfaces/terminal/components/StatusBar.js +1 -0
- package/src/interfaces/terminal/components/TextInput.js +1 -0
- package/src/interfaces/terminal/config/agentEditorConstants.js +1 -0
- package/src/interfaces/terminal/config/constants.js +1 -0
- package/src/interfaces/terminal/index.js +1 -0
- package/src/interfaces/terminal/state/useAgentControl.js +1 -0
- package/src/interfaces/terminal/state/useAgents.js +1 -0
- package/src/interfaces/terminal/state/useConnection.js +1 -0
- package/src/interfaces/terminal/state/useMessages.js +1 -0
- package/src/interfaces/terminal/state/useTools.js +1 -0
- package/src/interfaces/terminal/utils/debugLogger.js +1 -0
- package/src/interfaces/terminal/utils/settingsStorage.js +1 -0
- package/src/interfaces/terminal/utils/theme.js +1 -0
- package/src/interfaces/webServer.js +1 -2162
- package/src/modules/fileExplorer/controller.js +1 -280
- package/src/modules/fileExplorer/index.js +1 -37
- package/src/modules/fileExplorer/middleware.js +1 -92
- package/src/modules/fileExplorer/routes.js +1 -125
- package/src/modules/fileExplorer/types.js +1 -44
- package/src/services/aiService.js +1 -1232
- package/src/services/apiKeyManager.js +1 -164
- package/src/services/benchmarkService.js +1 -366
- package/src/services/budgetService.js +1 -539
- package/src/services/contextInjectionService.js +1 -247
- package/src/services/conversationCompactionService.js +1 -637
- package/src/services/errorHandler.js +1 -810
- package/src/services/fileAttachmentService.js +1 -544
- package/src/services/modelRouterService.js +1 -366
- package/src/services/modelsService.js +1 -322
- package/src/services/qualityInspector.js +1 -796
- package/src/services/tokenCountingService.js +1 -536
- package/src/tools/agentCommunicationTool.js +1 -1344
- package/src/tools/agentDelayTool.js +1 -485
- package/src/tools/asyncToolManager.js +1 -604
- package/src/tools/baseTool.js +1 -800
- package/src/tools/browserTool.js +1 -920
- package/src/tools/cloneDetectionTool.js +1 -621
- package/src/tools/dependencyResolverTool.js +1 -1215
- package/src/tools/fileContentReplaceTool.js +1 -875
- package/src/tools/fileSystemTool.js +1 -1107
- package/src/tools/fileTreeTool.js +1 -853
- package/src/tools/imageTool.js +1 -901
- package/src/tools/importAnalyzerTool.js +1 -1060
- package/src/tools/jobDoneTool.js +1 -248
- package/src/tools/seekTool.js +1 -956
- package/src/tools/staticAnalysisTool.js +1 -1778
- package/src/tools/taskManagerTool.js +1 -2873
- package/src/tools/terminalTool.js +1 -2304
- package/src/tools/webTool.js +1 -1430
- package/src/types/agent.js +1 -519
- package/src/types/contextReference.js +1 -972
- package/src/types/conversation.js +1 -730
- package/src/types/toolCommand.js +1 -747
- package/src/utilities/attachmentValidator.js +1 -292
- package/src/utilities/configManager.js +1 -582
- package/src/utilities/constants.js +1 -722
- package/src/utilities/directoryAccessManager.js +1 -535
- package/src/utilities/fileProcessor.js +1 -307
- package/src/utilities/logger.js +1 -436
- package/src/utilities/tagParser.js +1 -1246
- package/src/utilities/toolConstants.js +1 -317
- package/web-ui/build/index.html +2 -2
- package/web-ui/build/static/{index-Dy2bYbOa.css → index-CClD1090.css} +1 -1
- package/web-ui/build/static/{index-CjkkcnFA.js → index-lCBai6dX.js} +66 -67
|
@@ -1,2147 +1 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* AgentScheduler - Manages cooperative execution of multiple agents
|
|
3
|
-
*
|
|
4
|
-
* Architecture:
|
|
5
|
-
* - Iterates over all active agents in round-robin fashion
|
|
6
|
-
* - For each agent, processes queued messages (toolResults, interAgentMessages, userMessages) in arrival order
|
|
7
|
-
* - Sends conversation history to AI service for completion
|
|
8
|
-
* - Handles agent mode differences (CHAT vs AGENT)
|
|
9
|
-
* - Respects agent delays set by agentDelay tool
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
import {
|
|
13
|
-
AGENT_MODES,
|
|
14
|
-
AGENT_MODE_STATES,
|
|
15
|
-
MESSAGE_ROLES,
|
|
16
|
-
COMPACTION_CONFIG,
|
|
17
|
-
COMPACTION_STATUS,
|
|
18
|
-
COMPACTION_STRATEGIES,
|
|
19
|
-
TOKEN_COUNTING_MODES
|
|
20
|
-
} from '../utilities/constants.js';
|
|
21
|
-
import ContextInjectionService from '../services/contextInjectionService.js';
|
|
22
|
-
import TokenCountingService from '../services/tokenCountingService.js';
|
|
23
|
-
import ConversationCompactionService from '../services/conversationCompactionService.js';
|
|
24
|
-
|
|
25
|
-
class AgentScheduler {
|
|
26
|
-
constructor(agentPool, messageProcessor, aiService, logger, webSocketManager = null, modelRouterService = null, modelsService = null) {
|
|
27
|
-
this.agentPool = agentPool;
|
|
28
|
-
this.messageProcessor = messageProcessor;
|
|
29
|
-
this.aiService = aiService;
|
|
30
|
-
this.logger = logger;
|
|
31
|
-
this.webSocketManager = webSocketManager;
|
|
32
|
-
this.modelRouterService = modelRouterService;
|
|
33
|
-
this.modelsService = modelsService;
|
|
34
|
-
|
|
35
|
-
// Initialize ContextInjectionService for file attachments
|
|
36
|
-
this.contextInjectionService = new ContextInjectionService({}, logger);
|
|
37
|
-
|
|
38
|
-
// Initialize compactization services
|
|
39
|
-
this.tokenCountingService = new TokenCountingService(logger);
|
|
40
|
-
this.compactionService = new ConversationCompactionService(
|
|
41
|
-
this.tokenCountingService,
|
|
42
|
-
aiService,
|
|
43
|
-
logger
|
|
44
|
-
);
|
|
45
|
-
|
|
46
|
-
// Compactization state tracking
|
|
47
|
-
this.compactionInProgress = new Map(); // Map of agentId to compaction status
|
|
48
|
-
|
|
49
|
-
// Scheduler state
|
|
50
|
-
this.isRunning = false;
|
|
51
|
-
this.activeAgents = new Map(); // Map of agentId to context (includes sessionId)
|
|
52
|
-
this.scheduleInterval = null;
|
|
53
|
-
|
|
54
|
-
// Duplicate processing prevention
|
|
55
|
-
this.processedStateHashes = new Map(); // Map of agentId to Set of processed state hashes
|
|
56
|
-
|
|
57
|
-
// Concurrency control - prevent multiple processing cycles
|
|
58
|
-
this.processingInProgress = false;
|
|
59
|
-
this.agentProcessingLocks = new Map(); // Map of agentId to processing state
|
|
60
|
-
|
|
61
|
-
// Configuration
|
|
62
|
-
this.ITERATION_DELAY = 1000; // ms between agent iterations
|
|
63
|
-
this.MAX_ITERATIONS_PER_CYCLE = 100000; // Safety limit
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
* Start the agent scheduler
|
|
68
|
-
*/
|
|
69
|
-
start() {
|
|
70
|
-
if (this.isRunning) {
|
|
71
|
-
this.logger.info('Agent scheduler is already running');
|
|
72
|
-
return;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
this.isRunning = true;
|
|
76
|
-
this.logger.info('Starting Agent Scheduler with T/M/U queue system');
|
|
77
|
-
|
|
78
|
-
// Initialize existing AGENT mode agents
|
|
79
|
-
this.initializeExistingAgents();
|
|
80
|
-
|
|
81
|
-
// Start the main scheduler loop
|
|
82
|
-
this.scheduleInterval = setInterval(() => {
|
|
83
|
-
this.processingCycle().catch(error => {
|
|
84
|
-
this.logger.error('Scheduler processing cycle failed:', error);
|
|
85
|
-
});
|
|
86
|
-
}, this.ITERATION_DELAY);
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
/**
|
|
90
|
-
* Initialize existing AGENT mode agents into the scheduler
|
|
91
|
-
* Called on scheduler startup to ensure all AGENT mode agents are active
|
|
92
|
-
* @private
|
|
93
|
-
*/
|
|
94
|
-
async initializeExistingAgents() {
|
|
95
|
-
try {
|
|
96
|
-
// Get all agents from the pool
|
|
97
|
-
const allAgents = await this.agentPool.getAllAgents();
|
|
98
|
-
|
|
99
|
-
let addedCount = 0;
|
|
100
|
-
for (const agent of allAgents) {
|
|
101
|
-
// Add AGENT mode agents to scheduler
|
|
102
|
-
if (agent.mode === AGENT_MODES.AGENT) {
|
|
103
|
-
this.logger.info(`Initializing existing AGENT mode agent: ${agent.id}`, {
|
|
104
|
-
agentName: agent.name,
|
|
105
|
-
sessionId: agent.sessionId
|
|
106
|
-
});
|
|
107
|
-
|
|
108
|
-
// Check if agent is already in scheduler with a sessionId
|
|
109
|
-
const existingContext = this.activeAgents.get(agent.id);
|
|
110
|
-
const sessionId = existingContext?.sessionId || agent.sessionId;
|
|
111
|
-
|
|
112
|
-
await this.addAgent(agent.id, {
|
|
113
|
-
sessionId: sessionId, // Preserve existing sessionId if available
|
|
114
|
-
triggeredBy: 'scheduler-startup',
|
|
115
|
-
reason: 'Agent was already in AGENT mode'
|
|
116
|
-
});
|
|
117
|
-
|
|
118
|
-
addedCount++;
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
this.logger.info(`Initialized ${addedCount} existing AGENT mode agents into scheduler`);
|
|
123
|
-
|
|
124
|
-
} catch (error) {
|
|
125
|
-
this.logger.error('Failed to initialize existing agents', {
|
|
126
|
-
error: error.message
|
|
127
|
-
});
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
/**
|
|
132
|
-
* Stop the agent scheduler
|
|
133
|
-
*/
|
|
134
|
-
stop() {
|
|
135
|
-
if (!this.isRunning) return;
|
|
136
|
-
|
|
137
|
-
this.isRunning = false;
|
|
138
|
-
if (this.scheduleInterval) {
|
|
139
|
-
clearInterval(this.scheduleInterval);
|
|
140
|
-
this.scheduleInterval = null;
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
this.activeAgents.clear();
|
|
144
|
-
this.compactionInProgress.clear();
|
|
145
|
-
|
|
146
|
-
// Cleanup services
|
|
147
|
-
if (this.tokenCountingService && this.tokenCountingService.cleanup) {
|
|
148
|
-
this.tokenCountingService.cleanup();
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
this.logger.info('Agent Scheduler stopped');
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
/**
|
|
155
|
-
* Add agent to scheduler for processing
|
|
156
|
-
* @param {string} agentId - Agent ID to add
|
|
157
|
-
* @param {Object} context - Processing context
|
|
158
|
-
*/
|
|
159
|
-
async addAgent(agentId, context = {}) {
|
|
160
|
-
const agent = await this.agentPool.getAgent(agentId);
|
|
161
|
-
if (!agent) {
|
|
162
|
-
this.logger.warn(`Cannot add agent to scheduler - agent not found: ${agentId}`);
|
|
163
|
-
return;
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
if (agent.status !== 'active') {
|
|
167
|
-
this.logger.debug(`Skipping inactive agent: ${agentId} (status: ${agent.status})`);
|
|
168
|
-
return;
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
// Store agent with its context (including sessionId)
|
|
172
|
-
// CRITICAL FIX: Don't use fallback session IDs that break API key resolution
|
|
173
|
-
if (!context.sessionId) {
|
|
174
|
-
this.logger.warn(`Agent ${agentId} added to scheduler without sessionId - API key resolution may fail`, {
|
|
175
|
-
agentName: agent.name,
|
|
176
|
-
triggeredBy: context.triggeredBy
|
|
177
|
-
});
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
this.activeAgents.set(agentId, {
|
|
181
|
-
sessionId: context.sessionId, // NO FALLBACK - preserve original session ID or undefined
|
|
182
|
-
triggeredBy: context.triggeredBy || 'unknown',
|
|
183
|
-
addedAt: new Date().toISOString()
|
|
184
|
-
});
|
|
185
|
-
|
|
186
|
-
// Initialize hash tracking for this agent if not exists
|
|
187
|
-
if (!this.processedStateHashes.has(agentId)) {
|
|
188
|
-
this.processedStateHashes.set(agentId, new Set());
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
this.logger.info(`Agent added to scheduler: ${agentId}`, {
|
|
192
|
-
agentMode: agent.mode,
|
|
193
|
-
activeAgents: this.activeAgents.size,
|
|
194
|
-
sessionId: context.sessionId || 'NO_SESSION_ID',
|
|
195
|
-
contextKeys: Object.keys(context),
|
|
196
|
-
triggeredBy: context.triggeredBy || 'unknown'
|
|
197
|
-
});
|
|
198
|
-
|
|
199
|
-
// Start scheduler if not running
|
|
200
|
-
if (!this.isRunning) {
|
|
201
|
-
this.start();
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
/**
|
|
206
|
-
* Remove agent from scheduler
|
|
207
|
-
* @param {string} agentId - Agent ID to remove
|
|
208
|
-
* @param {string} reason - Reason for removal
|
|
209
|
-
*/
|
|
210
|
-
removeAgent(agentId, reason = 'completed') {
|
|
211
|
-
if (this.activeAgents.has(agentId)) {
|
|
212
|
-
this.activeAgents.delete(agentId);
|
|
213
|
-
|
|
214
|
-
// Clean up processed state hashes for this agent
|
|
215
|
-
this.processedStateHashes.delete(agentId);
|
|
216
|
-
|
|
217
|
-
this.logger.info(`Agent removed from scheduler: ${agentId}`, {
|
|
218
|
-
reason,
|
|
219
|
-
remainingAgents: this.activeAgents.size
|
|
220
|
-
});
|
|
221
|
-
|
|
222
|
-
// Stop scheduler if no active agents
|
|
223
|
-
if (this.activeAgents.size === 0) {
|
|
224
|
-
this.stop();
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
/**
|
|
230
|
-
* Check if agent is currently in scheduler
|
|
231
|
-
* @param {string} agentId - Agent ID to check
|
|
232
|
-
* @returns {boolean} True if agent is in scheduler
|
|
233
|
-
*/
|
|
234
|
-
isAgentInScheduler(agentId) {
|
|
235
|
-
return this.activeAgents.has(agentId);
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
/**
|
|
239
|
-
* Stop autonomous execution for a specific agent
|
|
240
|
-
* @param {string} agentId - Agent ID to stop
|
|
241
|
-
* @returns {Promise<Object>} Result with agent state
|
|
242
|
-
*/
|
|
243
|
-
async stopAgentExecution(agentId) {
|
|
244
|
-
try {
|
|
245
|
-
const agent = await this.agentPool.getAgent(agentId);
|
|
246
|
-
if (!agent) {
|
|
247
|
-
return {
|
|
248
|
-
success: false,
|
|
249
|
-
error: 'Agent not found'
|
|
250
|
-
};
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
// Set agent mode back to CHAT
|
|
254
|
-
agent.mode = AGENT_MODES.CHAT;
|
|
255
|
-
agent.modeState = AGENT_MODE_STATES.IDLE;
|
|
256
|
-
|
|
257
|
-
// Clear any delays
|
|
258
|
-
agent.delayEndTime = null;
|
|
259
|
-
|
|
260
|
-
// Persist the change
|
|
261
|
-
await this.agentPool.persistAgentState(agentId);
|
|
262
|
-
|
|
263
|
-
// Remove from scheduler
|
|
264
|
-
this.removeAgent(agentId, 'stopped-by-user');
|
|
265
|
-
|
|
266
|
-
// Get session ID for broadcast
|
|
267
|
-
const agentContext = this.activeAgents.get(agentId);
|
|
268
|
-
const sessionId = agentContext?.sessionId || agent.sessionId;
|
|
269
|
-
|
|
270
|
-
// Log warning if no session ID but continue with broadcast
|
|
271
|
-
if (!sessionId) {
|
|
272
|
-
this.logger.warn(`Agent ${agentId} stopped but has no session ID for broadcast`, {
|
|
273
|
-
agentName: agent.name
|
|
274
|
-
});
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
// Broadcast stop event only if we have a valid session ID
|
|
278
|
-
if (sessionId && this.webSocketManager && this.webSocketManager.broadcastToSession) {
|
|
279
|
-
this.webSocketManager.broadcastToSession(sessionId, {
|
|
280
|
-
type: 'execution_stopped',
|
|
281
|
-
data: {
|
|
282
|
-
agentId,
|
|
283
|
-
type: 'execution_stopped',
|
|
284
|
-
modeState: 'stopped',
|
|
285
|
-
timestamp: new Date().toISOString()
|
|
286
|
-
}
|
|
287
|
-
});
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
this.logger.info(`Agent execution stopped: ${agentId}`, {
|
|
291
|
-
mode: agent.mode,
|
|
292
|
-
modeState: agent.modeState
|
|
293
|
-
});
|
|
294
|
-
|
|
295
|
-
return {
|
|
296
|
-
success: true,
|
|
297
|
-
agent: {
|
|
298
|
-
id: agent.id,
|
|
299
|
-
name: agent.name,
|
|
300
|
-
mode: agent.mode,
|
|
301
|
-
modeState: agent.modeState
|
|
302
|
-
}
|
|
303
|
-
};
|
|
304
|
-
|
|
305
|
-
} catch (error) {
|
|
306
|
-
this.logger.error(`Failed to stop agent execution: ${agentId}`, {
|
|
307
|
-
error: error.message
|
|
308
|
-
});
|
|
309
|
-
|
|
310
|
-
return {
|
|
311
|
-
success: false,
|
|
312
|
-
error: error.message
|
|
313
|
-
};
|
|
314
|
-
}
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
/**
|
|
318
|
-
* Main processing cycle - iterates over all active agents
|
|
319
|
-
* @private
|
|
320
|
-
*/
|
|
321
|
-
async processingCycle() {
|
|
322
|
-
// Prevent concurrent processing cycles
|
|
323
|
-
if (this.processingInProgress) {
|
|
324
|
-
this.logger.debug('Processing cycle already in progress, skipping');
|
|
325
|
-
return;
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
if (this.activeAgents.size === 0) {
|
|
329
|
-
return; // No agents to process
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
this.processingInProgress = true;
|
|
333
|
-
|
|
334
|
-
try {
|
|
335
|
-
const agentIds = Array.from(this.activeAgents.keys());
|
|
336
|
-
|
|
337
|
-
for (const agentId of agentIds) {
|
|
338
|
-
try {
|
|
339
|
-
// Skip if agent was removed during this cycle
|
|
340
|
-
if (!this.activeAgents.has(agentId)) continue;
|
|
341
|
-
|
|
342
|
-
const shouldContinue = await this.processAgent(agentId);
|
|
343
|
-
|
|
344
|
-
if (!shouldContinue) {
|
|
345
|
-
this.removeAgent(agentId, 'completed');
|
|
346
|
-
}
|
|
347
|
-
|
|
348
|
-
} catch (error) {
|
|
349
|
-
this.logger.error(`Agent processing failed: ${agentId}`, {
|
|
350
|
-
error: error.message,
|
|
351
|
-
stack: error.stack
|
|
352
|
-
});
|
|
353
|
-
|
|
354
|
-
this.removeAgent(agentId, 'error');
|
|
355
|
-
}
|
|
356
|
-
}
|
|
357
|
-
} finally {
|
|
358
|
-
this.processingInProgress = false;
|
|
359
|
-
}
|
|
360
|
-
}
|
|
361
|
-
|
|
362
|
-
/**
|
|
363
|
-
* Process a single agent - handle queues and get AI response
|
|
364
|
-
* @param {string} agentId - Agent ID to process
|
|
365
|
-
* @returns {Promise<boolean>} Whether agent should continue in scheduler
|
|
366
|
-
* @private
|
|
367
|
-
*/
|
|
368
|
-
async processAgent(agentId) {
|
|
369
|
-
// Check if this agent is already being processed
|
|
370
|
-
if (this.agentProcessingLocks.get(agentId)) {
|
|
371
|
-
this.logger.debug(`Agent ${agentId} is already being processed, skipping`);
|
|
372
|
-
return true; // Continue in scheduler but skip this iteration
|
|
373
|
-
}
|
|
374
|
-
|
|
375
|
-
const agent = await this.agentPool.getAgent(agentId);
|
|
376
|
-
if (!agent) {
|
|
377
|
-
return false; // Agent no longer exists
|
|
378
|
-
}
|
|
379
|
-
|
|
380
|
-
// Set processing lock
|
|
381
|
-
this.agentProcessingLocks.set(agentId, true);
|
|
382
|
-
|
|
383
|
-
try {
|
|
384
|
-
// Check if agent is delayed
|
|
385
|
-
if (agent.delayEndTime && new Date() < new Date(agent.delayEndTime)) {
|
|
386
|
-
this.logger.debug(`Agent ${agentId} is delayed until ${agent.delayEndTime}`);
|
|
387
|
-
return true; // Continue in scheduler but skip this iteration
|
|
388
|
-
}
|
|
389
|
-
|
|
390
|
-
// Check if agent is paused
|
|
391
|
-
if (agent.status === 'paused' || agent.pausedUntil) {
|
|
392
|
-
if (agent.pausedUntil && new Date() < new Date(agent.pausedUntil)) {
|
|
393
|
-
this.logger.debug(`Agent ${agentId} is paused until ${agent.pausedUntil}`);
|
|
394
|
-
return true; // Continue in scheduler but skip this iteration
|
|
395
|
-
}
|
|
396
|
-
}
|
|
397
|
-
|
|
398
|
-
// Check stop request
|
|
399
|
-
if (agent.stopRequested) {
|
|
400
|
-
this.logger.info(`Agent ${agentId} stop requested - removing from scheduler`);
|
|
401
|
-
return false;
|
|
402
|
-
}
|
|
403
|
-
|
|
404
|
-
// Generate current state hash
|
|
405
|
-
const currentStateHash = this.generateAgentStateHash(agent);
|
|
406
|
-
|
|
407
|
-
// Check if we've already processed this exact state
|
|
408
|
-
if (this.hasProcessedState(agentId, currentStateHash)) {
|
|
409
|
-
this.logger.debug(`Agent ${agentId} state already processed, skipping duplicate iteration`, {
|
|
410
|
-
stateHash: currentStateHash,
|
|
411
|
-
agentMode: agent.mode
|
|
412
|
-
});
|
|
413
|
-
|
|
414
|
-
// CRITICAL FIX: CHAT agents with no new messages should be removed, not kept in scheduler
|
|
415
|
-
// Only AGENT agents should wait for backend responses with duplicate states
|
|
416
|
-
if (agent.mode === AGENT_MODES.CHAT) {
|
|
417
|
-
const hasNewMessages = agent.messageQueues.userMessages.length > 0 ||
|
|
418
|
-
agent.messageQueues.interAgentMessages.length > 0;
|
|
419
|
-
|
|
420
|
-
if (!hasNewMessages) {
|
|
421
|
-
this.logger.debug(`CHAT agent ${agentId} has duplicate state with no new messages - removing from scheduler`);
|
|
422
|
-
return false; // Remove CHAT agents with no new messages
|
|
423
|
-
}
|
|
424
|
-
}
|
|
425
|
-
|
|
426
|
-
// AGENT agents: skip this iteration but keep in scheduler
|
|
427
|
-
// Don't exit - backend responses might still arrive
|
|
428
|
-
return true;
|
|
429
|
-
}
|
|
430
|
-
|
|
431
|
-
// REFACTORED: Unified processing path with priority handling
|
|
432
|
-
// User messages are processed first by processAgentQueues (it sorts by priority)
|
|
433
|
-
const queues = agent.messageQueues;
|
|
434
|
-
|
|
435
|
-
// Log if user messages are present (highest priority)
|
|
436
|
-
if (queues.userMessages.length > 0) {
|
|
437
|
-
this.logger.info(`User message detected for agent ${agentId} - will be prioritized`, {
|
|
438
|
-
userMessageCount: queues.userMessages.length,
|
|
439
|
-
agentMode: agent.mode
|
|
440
|
-
});
|
|
441
|
-
}
|
|
442
|
-
|
|
443
|
-
// Check if agent has any messages to process
|
|
444
|
-
const totalMessages = queues.toolResults.length + queues.interAgentMessages.length + queues.userMessages.length;
|
|
445
|
-
|
|
446
|
-
if (totalMessages === 0 && agent.mode === AGENT_MODES.CHAT) {
|
|
447
|
-
// CHAT agents with no messages are removed from scheduler
|
|
448
|
-
this.logger.debug(`CHAT agent ${agentId} has no queued messages - removing from scheduler`);
|
|
449
|
-
return false;
|
|
450
|
-
}
|
|
451
|
-
|
|
452
|
-
if (totalMessages === 0 && agent.mode === AGENT_MODES.AGENT) {
|
|
453
|
-
// Check if we should auto-create initial task for conversation
|
|
454
|
-
await this.autoCreateInitialTaskIfNeeded(agentId);
|
|
455
|
-
|
|
456
|
-
// AGENT agents need pending tasks or unprocessed messages to continue
|
|
457
|
-
const hasPendingTasks = this.hasPendingTasks(agent);
|
|
458
|
-
const hasUnprocessedMessages = this.hasUnprocessedMessages(agent);
|
|
459
|
-
|
|
460
|
-
if (!hasPendingTasks && !hasUnprocessedMessages) {
|
|
461
|
-
this.logger.info(`AGENT mode agent ${agentId} has no pending tasks or messages - removing from scheduler`, {
|
|
462
|
-
agentName: agent.name,
|
|
463
|
-
taskCount: agent.taskList?.tasks?.length || 0,
|
|
464
|
-
completedTasks: agent.taskList?.tasks?.filter(t => t.status === 'completed').length || 0
|
|
465
|
-
});
|
|
466
|
-
return false; // Remove from scheduler when no work remaining
|
|
467
|
-
}
|
|
468
|
-
|
|
469
|
-
// Continue running autonomously if has work
|
|
470
|
-
return await this.processAgentAutonomously(agentId);
|
|
471
|
-
}
|
|
472
|
-
|
|
473
|
-
// Process queued messages in arrival order
|
|
474
|
-
const processedMessages = await this.processAgentQueues(agentId);
|
|
475
|
-
|
|
476
|
-
if (processedMessages === 0) {
|
|
477
|
-
// No messages processed
|
|
478
|
-
if (agent.mode === AGENT_MODES.CHAT) {
|
|
479
|
-
return false; // Remove CHAT agents with no messages
|
|
480
|
-
} else {
|
|
481
|
-
return await this.processAgentAutonomously(agentId); // Continue AGENT agents
|
|
482
|
-
}
|
|
483
|
-
}
|
|
484
|
-
|
|
485
|
-
// Get AI response after processing queued messages
|
|
486
|
-
const aiResponse = await this.getAgentAIResponse(agentId);
|
|
487
|
-
|
|
488
|
-
if (!aiResponse) {
|
|
489
|
-
this.logger.warn(`No AI response for agent ${agentId}`);
|
|
490
|
-
return agent.mode === AGENT_MODES.AGENT; // Keep AGENT agents, remove CHAT agents
|
|
491
|
-
}
|
|
492
|
-
|
|
493
|
-
// Process AI response and execute any tools (broadcasts to UI, executes tools)
|
|
494
|
-
await this.processAIResponse(agentId, aiResponse);
|
|
495
|
-
|
|
496
|
-
// Mark this state as processed after successful completion
|
|
497
|
-
this.markStateAsProcessed(agentId, currentStateHash);
|
|
498
|
-
|
|
499
|
-
// Determine if agent should continue in scheduler
|
|
500
|
-
return this.shouldAgentContinue(agentId, agent);
|
|
501
|
-
|
|
502
|
-
} finally {
|
|
503
|
-
// Always clear processing lock, even on errors
|
|
504
|
-
this.agentProcessingLocks.delete(agentId);
|
|
505
|
-
}
|
|
506
|
-
}
|
|
507
|
-
|
|
508
|
-
/**
|
|
509
|
-
* Process agent's message queues with consolidated single-message approach
|
|
510
|
-
* @param {string} agentId - Agent ID
|
|
511
|
-
* @returns {Promise<number>} Number of messages processed
|
|
512
|
-
* @private
|
|
513
|
-
*/
|
|
514
|
-
async processAgentQueues(agentId) {
|
|
515
|
-
const agent = await this.agentPool.getAgent(agentId);
|
|
516
|
-
if (!agent) return 0;
|
|
517
|
-
|
|
518
|
-
const queues = agent.messageQueues;
|
|
519
|
-
|
|
520
|
-
// Collect all messages with timestamps for proper ordering
|
|
521
|
-
const allMessages = [
|
|
522
|
-
...queues.toolResults.map(msg => ({ ...msg, queueType: 'toolResults' })),
|
|
523
|
-
...queues.interAgentMessages.map(msg => ({ ...msg, queueType: 'interAgentMessages' })),
|
|
524
|
-
...queues.userMessages.map(msg => ({ ...msg, queueType: 'userMessages' }))
|
|
525
|
-
];
|
|
526
|
-
|
|
527
|
-
if (allMessages.length === 0) return 0;
|
|
528
|
-
|
|
529
|
-
// Sort by arrival time (timestamp)
|
|
530
|
-
allMessages.sort((a, b) => new Date(a.timestamp || a.queuedAt || 0) - new Date(b.timestamp || b.queuedAt || 0));
|
|
531
|
-
|
|
532
|
-
// CRITICAL FIX: Consolidate all messages into single AI request
|
|
533
|
-
let consolidatedContent = '';
|
|
534
|
-
const hasUserMessages = allMessages.some(m => m.queueType === 'userMessages');
|
|
535
|
-
const hasInterAgentMessages = allMessages.some(m => m.queueType === 'interAgentMessages');
|
|
536
|
-
const hasToolResults = allMessages.some(m => m.queueType === 'toolResults');
|
|
537
|
-
|
|
538
|
-
// Add user messages first (highest priority)
|
|
539
|
-
const userMessages = allMessages.filter(m => m.queueType === 'userMessages');
|
|
540
|
-
if (userMessages.length > 0) {
|
|
541
|
-
userMessages.forEach(msg => {
|
|
542
|
-
if (consolidatedContent) consolidatedContent += '\n\n';
|
|
543
|
-
consolidatedContent += msg.content;
|
|
544
|
-
});
|
|
545
|
-
}
|
|
546
|
-
|
|
547
|
-
// Add inter-agent messages as context (not as separate system messages)
|
|
548
|
-
const interAgentMessages = allMessages.filter(m => m.queueType === 'interAgentMessages');
|
|
549
|
-
if (interAgentMessages.length > 0) {
|
|
550
|
-
if (consolidatedContent) consolidatedContent += '\n\n';
|
|
551
|
-
consolidatedContent += '[Agent Messages]\n';
|
|
552
|
-
interAgentMessages.forEach(msg => {
|
|
553
|
-
const senderName = msg.senderName || msg.sender || 'Unknown Agent';
|
|
554
|
-
consolidatedContent += `${senderName}: ${msg.content}\n`;
|
|
555
|
-
});
|
|
556
|
-
}
|
|
557
|
-
|
|
558
|
-
// Add tool results as context
|
|
559
|
-
const toolResults = allMessages.filter(m => m.queueType === 'toolResults');
|
|
560
|
-
if (toolResults.length > 0) {
|
|
561
|
-
if (consolidatedContent) consolidatedContent += '\n\n';
|
|
562
|
-
consolidatedContent += '[Previous Tool Results]\n';
|
|
563
|
-
toolResults.forEach(msg => {
|
|
564
|
-
consolidatedContent += `${this.formatToolResult(msg)}\n`;
|
|
565
|
-
});
|
|
566
|
-
}
|
|
567
|
-
|
|
568
|
-
// Add processing instructions only if needed
|
|
569
|
-
if (hasInterAgentMessages) {
|
|
570
|
-
consolidatedContent += '\nNote: Use the agentcommunication tool if you need to respond to other agents.';
|
|
571
|
-
}
|
|
572
|
-
|
|
573
|
-
// PHASE 2: Auto-create tasks for incoming messages
|
|
574
|
-
await this.autoCreateTasksForMessages(agentId, userMessages, interAgentMessages);
|
|
575
|
-
|
|
576
|
-
// Create single consolidated user message for AI processing
|
|
577
|
-
const consolidatedMessage = {
|
|
578
|
-
id: `consolidated-${Date.now()}`,
|
|
579
|
-
role: MESSAGE_ROLES.USER,
|
|
580
|
-
content: consolidatedContent.trim(),
|
|
581
|
-
timestamp: new Date().toISOString(),
|
|
582
|
-
type: 'consolidated-input',
|
|
583
|
-
originalMessageCount: allMessages.length
|
|
584
|
-
};
|
|
585
|
-
|
|
586
|
-
// Add to conversation history (don't broadcast - this is internal)
|
|
587
|
-
await this.addMessageToConversation(agentId, consolidatedMessage, false);
|
|
588
|
-
|
|
589
|
-
// CRITICAL: Update conversation tracking when inter-agent messages are processed
|
|
590
|
-
if (agent && interAgentMessages.length > 0) {
|
|
591
|
-
for (const msg of interAgentMessages) {
|
|
592
|
-
if (msg.sender) {
|
|
593
|
-
// Mark that this agent received a message from the sender
|
|
594
|
-
if (!agent.interAgentTracking.has(msg.sender)) {
|
|
595
|
-
agent.interAgentTracking.set(msg.sender, {
|
|
596
|
-
lastSent: null,
|
|
597
|
-
lastReceived: null,
|
|
598
|
-
lastType: null
|
|
599
|
-
});
|
|
600
|
-
}
|
|
601
|
-
|
|
602
|
-
const tracking = agent.interAgentTracking.get(msg.sender);
|
|
603
|
-
tracking.lastReceived = Date.now();
|
|
604
|
-
tracking.lastType = 'received';
|
|
605
|
-
}
|
|
606
|
-
}
|
|
607
|
-
// Persist updated tracking
|
|
608
|
-
await this.agentPool.persistAgentState(agentId);
|
|
609
|
-
}
|
|
610
|
-
|
|
611
|
-
// Clear all processed queues
|
|
612
|
-
queues.toolResults.length = 0;
|
|
613
|
-
queues.interAgentMessages.length = 0;
|
|
614
|
-
queues.userMessages.length = 0;
|
|
615
|
-
|
|
616
|
-
// Persist updated agent state
|
|
617
|
-
await this.agentPool.persistAgentState(agentId);
|
|
618
|
-
|
|
619
|
-
this.logger.debug(`Consolidated ${allMessages.length} queued messages for agent ${agentId}`);
|
|
620
|
-
return allMessages.length;
|
|
621
|
-
}
|
|
622
|
-
|
|
623
|
-
/**
|
|
624
|
-
* Add message to agent's conversation history with proper formatting
|
|
625
|
-
* @param {string} agentId - Agent ID
|
|
626
|
-
* @param {Object} message - Message to add
|
|
627
|
-
* @param {boolean} broadcast - Whether to broadcast message to UI (default true)
|
|
628
|
-
* @private
|
|
629
|
-
*/
|
|
630
|
-
async addMessageToConversation(agentId, message, broadcast = true) {
|
|
631
|
-
const agent = await this.agentPool.getAgent(agentId);
|
|
632
|
-
if (!agent) return;
|
|
633
|
-
|
|
634
|
-
// Format message based on queue type
|
|
635
|
-
let formattedMessage;
|
|
636
|
-
|
|
637
|
-
switch (message.queueType) {
|
|
638
|
-
case 'toolResults': // Tool results
|
|
639
|
-
formattedMessage = {
|
|
640
|
-
...message,
|
|
641
|
-
role: 'tool',
|
|
642
|
-
content: this.formatToolResult(message)
|
|
643
|
-
};
|
|
644
|
-
break;
|
|
645
|
-
|
|
646
|
-
case 'interAgentMessages': // Inter-agent messages
|
|
647
|
-
formattedMessage = {
|
|
648
|
-
...message,
|
|
649
|
-
role: MESSAGE_ROLES.SYSTEM,
|
|
650
|
-
content: `Message from ${message.senderName || message.sender}: ${message.content}`
|
|
651
|
-
};
|
|
652
|
-
break;
|
|
653
|
-
|
|
654
|
-
case 'userMessages': // User messages
|
|
655
|
-
formattedMessage = {
|
|
656
|
-
...message,
|
|
657
|
-
role: MESSAGE_ROLES.USER
|
|
658
|
-
};
|
|
659
|
-
break;
|
|
660
|
-
|
|
661
|
-
default:
|
|
662
|
-
formattedMessage = message;
|
|
663
|
-
}
|
|
664
|
-
|
|
665
|
-
// Add timestamp if not present
|
|
666
|
-
if (!formattedMessage.timestamp) {
|
|
667
|
-
formattedMessage.timestamp = new Date().toISOString();
|
|
668
|
-
}
|
|
669
|
-
|
|
670
|
-
// Add to conversation history
|
|
671
|
-
agent.conversations.full.messages.push(formattedMessage);
|
|
672
|
-
agent.conversations.full.lastUpdated = new Date().toISOString();
|
|
673
|
-
|
|
674
|
-
// Add to current model conversation if exists
|
|
675
|
-
if (agent.currentModel && agent.conversations[agent.currentModel]) {
|
|
676
|
-
agent.conversations[agent.currentModel].messages.push(formattedMessage);
|
|
677
|
-
agent.conversations[agent.currentModel].lastUpdated = new Date().toISOString();
|
|
678
|
-
}
|
|
679
|
-
|
|
680
|
-
// FIX: Only broadcast user-visible messages to UI (not internal system prompts)
|
|
681
|
-
if (broadcast && this.shouldBroadcastMessage(formattedMessage)) {
|
|
682
|
-
this.broadcastMessageUpdate(agentId, formattedMessage);
|
|
683
|
-
}
|
|
684
|
-
}
|
|
685
|
-
|
|
686
|
-
/**
|
|
687
|
-
* Process agent autonomously (for AGENT mode with no queued messages)
|
|
688
|
-
* @param {string} agentId - Agent ID
|
|
689
|
-
* @returns {Promise<boolean>} Whether agent should continue
|
|
690
|
-
* @private
|
|
691
|
-
*/
|
|
692
|
-
async processAgentAutonomously(agentId) {
|
|
693
|
-
// PHASE 2: Auto-mark the highest priority pending task as in-progress
|
|
694
|
-
await this.autoProgressHighestPriorityTask(agentId);
|
|
695
|
-
|
|
696
|
-
// Get AI response without new messages
|
|
697
|
-
const aiResponse = await this.getAgentAIResponse(agentId);
|
|
698
|
-
|
|
699
|
-
if (!aiResponse) {
|
|
700
|
-
return true; // Keep trying
|
|
701
|
-
}
|
|
702
|
-
|
|
703
|
-
// Process AI response and execute tools
|
|
704
|
-
await this.processAIResponse(agentId, aiResponse);
|
|
705
|
-
|
|
706
|
-
const agent = await this.agentPool.getAgent(agentId);
|
|
707
|
-
return this.shouldAgentContinue(agentId, agent);
|
|
708
|
-
}
|
|
709
|
-
|
|
710
|
-
/**
|
|
711
|
-
* Check if compaction is needed and perform it
|
|
712
|
-
* @param {string} agentId - Agent ID
|
|
713
|
-
* @param {string} targetModel - Target model for AI request
|
|
714
|
-
* @param {string} sessionId - Session ID for context
|
|
715
|
-
* @returns {Promise<Object>} Result with shouldContinue flag
|
|
716
|
-
* @private
|
|
717
|
-
*/
|
|
718
|
-
async checkAndPerformCompaction(agentId, targetModel, sessionId) {
|
|
719
|
-
const ENABLE_COMPACT_DEBUG = process.env.COMPACT_DEBUG === 'true';
|
|
720
|
-
|
|
721
|
-
if (ENABLE_COMPACT_DEBUG) {
|
|
722
|
-
console.log('[COMPACT-CHECK-START]', {
|
|
723
|
-
agentId,
|
|
724
|
-
targetModel,
|
|
725
|
-
sessionId,
|
|
726
|
-
timestamp: new Date().toISOString()
|
|
727
|
-
});
|
|
728
|
-
}
|
|
729
|
-
|
|
730
|
-
try {
|
|
731
|
-
const agent = await this.agentPool.getAgent(agentId);
|
|
732
|
-
if (!agent) {
|
|
733
|
-
if (ENABLE_COMPACT_DEBUG) {
|
|
734
|
-
console.log('[COMPACT-ERROR]', { agentId, reason: 'Agent not found' });
|
|
735
|
-
}
|
|
736
|
-
return { shouldContinue: false, error: 'Agent not found' };
|
|
737
|
-
}
|
|
738
|
-
|
|
739
|
-
// For model switching, check the current model's conversation, not the target model's
|
|
740
|
-
// This handles scenarios where we're switching from a larger context to a smaller one
|
|
741
|
-
let modelToCheck = agent.currentModel && agent.currentModel !== targetModel
|
|
742
|
-
? agent.currentModel
|
|
743
|
-
: targetModel;
|
|
744
|
-
|
|
745
|
-
// DEFENSIVE: If modelToCheck is undefined, try to find a valid conversation key
|
|
746
|
-
if (!modelToCheck) {
|
|
747
|
-
this.logger.warn(`Agent ${agentId} has no currentModel or targetModel set, attempting to use available conversation`, {
|
|
748
|
-
agentId,
|
|
749
|
-
currentModel: agent.currentModel,
|
|
750
|
-
targetModel,
|
|
751
|
-
preferredModel: agent.preferredModel,
|
|
752
|
-
availableConversations: Object.keys(agent.conversations || {})
|
|
753
|
-
});
|
|
754
|
-
|
|
755
|
-
// Notify user via WebSocket
|
|
756
|
-
this.broadcastCompactionEvent(agentId, sessionId, {
|
|
757
|
-
status: 'warning',
|
|
758
|
-
message: 'Agent model configuration issue detected - using fallback',
|
|
759
|
-
details: `Agent has no currentModel set. Using fallback model for compaction check.`,
|
|
760
|
-
agentName: agent.name
|
|
761
|
-
});
|
|
762
|
-
|
|
763
|
-
// Try preferredModel first
|
|
764
|
-
if (agent.preferredModel && agent.conversations[agent.preferredModel]) {
|
|
765
|
-
modelToCheck = agent.preferredModel;
|
|
766
|
-
this.logger.info(`Using preferredModel as fallback for compaction check: ${modelToCheck}`);
|
|
767
|
-
} else {
|
|
768
|
-
// Find any non-'full' conversation key
|
|
769
|
-
const conversationKeys = Object.keys(agent.conversations || {}).filter(key => key !== 'full');
|
|
770
|
-
if (conversationKeys.length > 0) {
|
|
771
|
-
modelToCheck = conversationKeys[0];
|
|
772
|
-
this.logger.warn(`Using first available conversation key for compaction check: ${modelToCheck}`);
|
|
773
|
-
} else {
|
|
774
|
-
this.logger.error(`No valid conversation found for agent ${agentId}, skipping compaction`);
|
|
775
|
-
|
|
776
|
-
// Notify user of critical error
|
|
777
|
-
this.broadcastCompactionEvent(agentId, sessionId, {
|
|
778
|
-
status: 'error',
|
|
779
|
-
message: 'No valid conversation found for compaction',
|
|
780
|
-
details: `Agent ${agent.name} has no valid conversation data. Compaction skipped.`,
|
|
781
|
-
agentName: agent.name
|
|
782
|
-
});
|
|
783
|
-
|
|
784
|
-
return { shouldContinue: true, error: 'No valid conversation found' };
|
|
785
|
-
}
|
|
786
|
-
}
|
|
787
|
-
}
|
|
788
|
-
|
|
789
|
-
// Get conversation metadata
|
|
790
|
-
const metadata = await this.agentPool.getCompactionMetadata(agentId, modelToCheck);
|
|
791
|
-
|
|
792
|
-
if (ENABLE_COMPACT_DEBUG) {
|
|
793
|
-
console.log('[COMPACT-METADATA]', {
|
|
794
|
-
agentId,
|
|
795
|
-
modelToCheck,
|
|
796
|
-
hasMetadata: !!metadata,
|
|
797
|
-
isCompacted: metadata?.isCompacted,
|
|
798
|
-
originalMessageCount: metadata?.originalMessages?.length || 0,
|
|
799
|
-
compactedMessageCount: metadata?.compactedMessages?.length || 0,
|
|
800
|
-
lastCompactization: metadata?.lastCompactization || 'never',
|
|
801
|
-
compactizationCount: metadata?.compactizationCount || 0,
|
|
802
|
-
originalTokenCount: metadata?.originalTokenCount || 0,
|
|
803
|
-
compactedTokenCount: metadata?.compactedTokenCount || 0
|
|
804
|
-
});
|
|
805
|
-
}
|
|
806
|
-
|
|
807
|
-
// If no conversation exists for this model yet, return early
|
|
808
|
-
if (!metadata || (!metadata.originalMessages && !metadata.compactedMessages)) {
|
|
809
|
-
this.logger.debug(`Compaction skipped: no conversation metadata for agent ${agentId}, model ${modelToCheck}`);
|
|
810
|
-
if (ENABLE_COMPACT_DEBUG) {
|
|
811
|
-
console.log('[COMPACT-SKIPPED]', { agentId, reason: 'No conversation metadata' });
|
|
812
|
-
}
|
|
813
|
-
return { shouldContinue: true }; // No conversation to compact
|
|
814
|
-
}
|
|
815
|
-
|
|
816
|
-
// Determine which messages to use for token counting
|
|
817
|
-
const messages = metadata.isCompacted
|
|
818
|
-
? metadata.compactedMessages
|
|
819
|
-
: metadata.originalMessages;
|
|
820
|
-
|
|
821
|
-
if (ENABLE_COMPACT_DEBUG) {
|
|
822
|
-
console.log('[COMPACT-MESSAGES-SELECTED]', {
|
|
823
|
-
agentId,
|
|
824
|
-
selectedArray: metadata.isCompacted ? 'compactedMessages' : 'originalMessages',
|
|
825
|
-
messageCount: messages?.length || 0,
|
|
826
|
-
reason: metadata.isCompacted ? 'Compaction exists, using compacted version' : 'No compaction yet, using original'
|
|
827
|
-
});
|
|
828
|
-
}
|
|
829
|
-
|
|
830
|
-
if (!messages || messages.length < COMPACTION_CONFIG.MIN_MESSAGES_FOR_COMPACTION) {
|
|
831
|
-
this.logger.debug(`Compaction skipped: too few messages (${messages?.length || 0}) for agent ${agentId}`);
|
|
832
|
-
if (ENABLE_COMPACT_DEBUG) {
|
|
833
|
-
console.log('[COMPACT-SKIPPED]', { agentId, reason: 'Too few messages', messageCount: messages?.length || 0, minRequired: COMPACTION_CONFIG.MIN_MESSAGES_FOR_COMPACTION });
|
|
834
|
-
}
|
|
835
|
-
return { shouldContinue: true }; // Conversation too short to compact
|
|
836
|
-
}
|
|
837
|
-
|
|
838
|
-
// Count current tokens
|
|
839
|
-
const currentTokens = await this.tokenCountingService.estimateConversationTokens(
|
|
840
|
-
messages,
|
|
841
|
-
targetModel,
|
|
842
|
-
TOKEN_COUNTING_MODES.ACCURATE
|
|
843
|
-
);
|
|
844
|
-
|
|
845
|
-
// Get model specifications
|
|
846
|
-
const contextWindow = this.tokenCountingService.getModelContextWindow(targetModel);
|
|
847
|
-
const maxOutputTokens = this.tokenCountingService.getModelMaxOutputTokens(targetModel);
|
|
848
|
-
|
|
849
|
-
if (ENABLE_COMPACT_DEBUG) {
|
|
850
|
-
console.log('[COMPACT-TOKEN-COUNT]', {
|
|
851
|
-
agentId,
|
|
852
|
-
currentTokens,
|
|
853
|
-
maxOutputTokens,
|
|
854
|
-
contextWindow,
|
|
855
|
-
model: targetModel,
|
|
856
|
-
countingMode: 'ACCURATE'
|
|
857
|
-
});
|
|
858
|
-
}
|
|
859
|
-
|
|
860
|
-
// Check if compaction is needed
|
|
861
|
-
const threshold = agent.compactionThreshold || COMPACTION_CONFIG.DEFAULT_THRESHOLD;
|
|
862
|
-
const shouldCompact = this.tokenCountingService.shouldTriggerCompaction(
|
|
863
|
-
currentTokens,
|
|
864
|
-
maxOutputTokens,
|
|
865
|
-
contextWindow,
|
|
866
|
-
threshold
|
|
867
|
-
);
|
|
868
|
-
|
|
869
|
-
if (ENABLE_COMPACT_DEBUG) {
|
|
870
|
-
const requiredTokens = currentTokens + maxOutputTokens;
|
|
871
|
-
const thresholdTokens = threshold * contextWindow;
|
|
872
|
-
console.log('[COMPACT-TRIGGER-CHECK]', {
|
|
873
|
-
agentId,
|
|
874
|
-
currentTokens,
|
|
875
|
-
maxOutputTokens,
|
|
876
|
-
requiredTokens,
|
|
877
|
-
contextWindow,
|
|
878
|
-
threshold,
|
|
879
|
-
thresholdTokens,
|
|
880
|
-
shouldCompact,
|
|
881
|
-
formula: `${currentTokens} + ${maxOutputTokens} = ${requiredTokens} ${shouldCompact ? '>=' : '<'} ${thresholdTokens} (${threshold * 100}% of ${contextWindow})`,
|
|
882
|
-
decision: shouldCompact ? 'TRIGGER COMPACTION' : 'SKIP - below threshold'
|
|
883
|
-
});
|
|
884
|
-
}
|
|
885
|
-
|
|
886
|
-
if (!shouldCompact) {
|
|
887
|
-
if (ENABLE_COMPACT_DEBUG) {
|
|
888
|
-
console.log('[COMPACT-SKIPPED]', { agentId, reason: 'Below threshold', utilizationPct: ((currentTokens + maxOutputTokens) / contextWindow * 100).toFixed(1) });
|
|
889
|
-
}
|
|
890
|
-
return { shouldContinue: true }; // No compaction needed
|
|
891
|
-
}
|
|
892
|
-
|
|
893
|
-
this.logger.info(`Compaction triggered for agent ${agentId}`, {
|
|
894
|
-
currentTokens,
|
|
895
|
-
contextWindow,
|
|
896
|
-
threshold: `${(threshold * 100).toFixed(0)}%`,
|
|
897
|
-
utilization: `${((currentTokens + maxOutputTokens) / contextWindow * 100).toFixed(1)}%`,
|
|
898
|
-
targetModel
|
|
899
|
-
});
|
|
900
|
-
|
|
901
|
-
if (ENABLE_COMPACT_DEBUG) {
|
|
902
|
-
console.log('[COMPACT-TRIGGERED]', {
|
|
903
|
-
agentId,
|
|
904
|
-
reason: 'Threshold exceeded',
|
|
905
|
-
currentTokens,
|
|
906
|
-
maxOutputTokens,
|
|
907
|
-
requiredTokens: currentTokens + maxOutputTokens,
|
|
908
|
-
contextWindow,
|
|
909
|
-
threshold,
|
|
910
|
-
utilizationPct: ((currentTokens + maxOutputTokens) / contextWindow * 100).toFixed(1)
|
|
911
|
-
});
|
|
912
|
-
}
|
|
913
|
-
|
|
914
|
-
// Mark compaction in progress
|
|
915
|
-
this.compactionInProgress.set(agentId, COMPACTION_STATUS.STARTING);
|
|
916
|
-
|
|
917
|
-
// Broadcast compaction started event
|
|
918
|
-
this.broadcastCompactionEvent(agentId, sessionId, {
|
|
919
|
-
status: COMPACTION_STATUS.STARTING,
|
|
920
|
-
currentTokens,
|
|
921
|
-
targetTokens: this.tokenCountingService.calculateTargetTokenCount(contextWindow),
|
|
922
|
-
contextWindow,
|
|
923
|
-
model: targetModel
|
|
924
|
-
});
|
|
925
|
-
|
|
926
|
-
// Determine strategy: If model switching, use truncation; otherwise use summarization
|
|
927
|
-
let strategy = COMPACTION_STRATEGIES.SUMMARIZATION;
|
|
928
|
-
const currentModel = agent.currentModel;
|
|
929
|
-
|
|
930
|
-
if (currentModel && currentModel !== targetModel) {
|
|
931
|
-
strategy = COMPACTION_STRATEGIES.TRUNCATION;
|
|
932
|
-
this.logger.info(`Using truncation strategy for model switch: ${currentModel} → ${targetModel}`);
|
|
933
|
-
}
|
|
934
|
-
|
|
935
|
-
// Update status to in-progress
|
|
936
|
-
this.compactionInProgress.set(agentId, COMPACTION_STATUS.IN_PROGRESS);
|
|
937
|
-
this.broadcastCompactionEvent(agentId, sessionId, {
|
|
938
|
-
status: COMPACTION_STATUS.IN_PROGRESS,
|
|
939
|
-
strategy,
|
|
940
|
-
messageCount: messages.length
|
|
941
|
-
});
|
|
942
|
-
|
|
943
|
-
// Perform compaction (with retry logic)
|
|
944
|
-
let compactionResult = null;
|
|
945
|
-
let attempts = 0;
|
|
946
|
-
const maxAttempts = COMPACTION_CONFIG.MAX_RETRY_ATTEMPTS;
|
|
947
|
-
|
|
948
|
-
while (attempts < maxAttempts && !compactionResult) {
|
|
949
|
-
attempts++;
|
|
950
|
-
|
|
951
|
-
try {
|
|
952
|
-
const currentStrategy = attempts === 1
|
|
953
|
-
? strategy
|
|
954
|
-
: COMPACTION_STRATEGIES.AGGRESSIVE; // Use aggressive on retry
|
|
955
|
-
|
|
956
|
-
compactionResult = await this.compactionService.compactConversation(
|
|
957
|
-
messages,
|
|
958
|
-
currentModel || targetModel,
|
|
959
|
-
targetModel,
|
|
960
|
-
{
|
|
961
|
-
strategy: currentStrategy,
|
|
962
|
-
targetTokenCount: this.tokenCountingService.calculateTargetTokenCount(contextWindow),
|
|
963
|
-
sessionId
|
|
964
|
-
}
|
|
965
|
-
);
|
|
966
|
-
|
|
967
|
-
// Validate compaction result
|
|
968
|
-
const validation = this.tokenCountingService.validateCompaction(
|
|
969
|
-
currentTokens,
|
|
970
|
-
compactionResult.compactedTokenCount,
|
|
971
|
-
contextWindow
|
|
972
|
-
);
|
|
973
|
-
|
|
974
|
-
if (!validation.valid) {
|
|
975
|
-
this.logger.warn(`Compaction validation failed for agent ${agentId}`, {
|
|
976
|
-
attempt: attempts,
|
|
977
|
-
reason: validation.reason,
|
|
978
|
-
reductionPercent: validation.reductionPercent
|
|
979
|
-
});
|
|
980
|
-
|
|
981
|
-
if (attempts < maxAttempts) {
|
|
982
|
-
compactionResult = null; // Retry with aggressive strategy
|
|
983
|
-
await new Promise(resolve => setTimeout(resolve, COMPACTION_CONFIG.RETRY_DELAY_MS));
|
|
984
|
-
}
|
|
985
|
-
}
|
|
986
|
-
|
|
987
|
-
} catch (error) {
|
|
988
|
-
this.logger.error(`Compaction attempt ${attempts} failed for agent ${agentId}`, {
|
|
989
|
-
error: error.message
|
|
990
|
-
});
|
|
991
|
-
|
|
992
|
-
if (attempts >= maxAttempts) {
|
|
993
|
-
throw error; // Final attempt failed
|
|
994
|
-
}
|
|
995
|
-
|
|
996
|
-
await new Promise(resolve => setTimeout(resolve, COMPACTION_CONFIG.RETRY_DELAY_MS));
|
|
997
|
-
}
|
|
998
|
-
}
|
|
999
|
-
|
|
1000
|
-
if (!compactionResult) {
|
|
1001
|
-
throw new Error('All compaction attempts failed');
|
|
1002
|
-
}
|
|
1003
|
-
|
|
1004
|
-
// For model switching, copy original messages to target model first
|
|
1005
|
-
if (currentModel && currentModel !== targetModel && modelToCheck === currentModel) {
|
|
1006
|
-
// Get the original messages from the current model
|
|
1007
|
-
const sourceMetadata = await this.agentPool.getCompactionMetadata(agentId, currentModel);
|
|
1008
|
-
if (sourceMetadata && sourceMetadata.originalMessages) {
|
|
1009
|
-
// Copy original messages to target model's conversation
|
|
1010
|
-
for (const message of sourceMetadata.originalMessages) {
|
|
1011
|
-
await this.agentPool.addMessageToConversation(agentId, targetModel, message);
|
|
1012
|
-
}
|
|
1013
|
-
this.logger.debug(`Copied ${sourceMetadata.originalMessages.length} messages from ${currentModel} to ${targetModel} for model switching`);
|
|
1014
|
-
}
|
|
1015
|
-
}
|
|
1016
|
-
|
|
1017
|
-
// Update AgentPool with compacted messages
|
|
1018
|
-
await this.agentPool.updateCompactedMessages(agentId, targetModel, compactionResult);
|
|
1019
|
-
|
|
1020
|
-
if (ENABLE_COMPACT_DEBUG) {
|
|
1021
|
-
console.log('[COMPACT-COMPLETED]', {
|
|
1022
|
-
agentId,
|
|
1023
|
-
strategy: compactionResult.strategy,
|
|
1024
|
-
originalMessageCount: compactionResult.originalMessages?.length || 0,
|
|
1025
|
-
compactedMessageCount: compactionResult.compactedMessages?.length || 0,
|
|
1026
|
-
originalTokens: compactionResult.originalTokenCount,
|
|
1027
|
-
compactedTokens: compactionResult.compactedTokenCount,
|
|
1028
|
-
reductionPercent: compactionResult.reductionPercent.toFixed(1),
|
|
1029
|
-
executionTimeMs: compactionResult.executionTime,
|
|
1030
|
-
model: targetModel
|
|
1031
|
-
});
|
|
1032
|
-
}
|
|
1033
|
-
|
|
1034
|
-
this.logger.info(`Compaction completed for agent ${agentId}`, {
|
|
1035
|
-
strategy: compactionResult.strategy,
|
|
1036
|
-
originalTokens: compactionResult.originalTokenCount,
|
|
1037
|
-
compactedTokens: compactionResult.compactedTokenCount,
|
|
1038
|
-
reduction: `${compactionResult.reductionPercent.toFixed(1)}%`,
|
|
1039
|
-
executionTime: `${compactionResult.executionTime}ms`
|
|
1040
|
-
});
|
|
1041
|
-
|
|
1042
|
-
// Update status to completed
|
|
1043
|
-
this.compactionInProgress.delete(agentId);
|
|
1044
|
-
this.broadcastCompactionEvent(agentId, sessionId, {
|
|
1045
|
-
status: COMPACTION_STATUS.COMPLETED,
|
|
1046
|
-
originalTokens: compactionResult.originalTokenCount,
|
|
1047
|
-
compactedTokens: compactionResult.compactedTokenCount,
|
|
1048
|
-
reductionPercent: compactionResult.reductionPercent,
|
|
1049
|
-
strategy: compactionResult.strategy,
|
|
1050
|
-
executionTime: compactionResult.executionTime
|
|
1051
|
-
});
|
|
1052
|
-
|
|
1053
|
-
return { shouldContinue: true, compactionPerformed: true };
|
|
1054
|
-
|
|
1055
|
-
} catch (error) {
|
|
1056
|
-
this.logger.error(`Compaction failed for agent ${agentId}`, {
|
|
1057
|
-
error: error.message,
|
|
1058
|
-
stack: error.stack
|
|
1059
|
-
});
|
|
1060
|
-
|
|
1061
|
-
// Update status to failed
|
|
1062
|
-
this.compactionInProgress.delete(agentId);
|
|
1063
|
-
this.broadcastCompactionEvent(agentId, sessionId, {
|
|
1064
|
-
status: COMPACTION_STATUS.FAILED,
|
|
1065
|
-
error: error.message
|
|
1066
|
-
});
|
|
1067
|
-
|
|
1068
|
-
// Don't block AI request on compaction failure
|
|
1069
|
-
return { shouldContinue: true, error: error.message };
|
|
1070
|
-
}
|
|
1071
|
-
}
|
|
1072
|
-
|
|
1073
|
-
/**
|
|
1074
|
-
* Broadcast compaction event to UI
|
|
1075
|
-
* @param {string} agentId - Agent ID
|
|
1076
|
-
* @param {string} sessionId - Session ID
|
|
1077
|
-
* @param {Object} data - Event data
|
|
1078
|
-
* @private
|
|
1079
|
-
*/
|
|
1080
|
-
broadcastCompactionEvent(agentId, sessionId, data) {
|
|
1081
|
-
if (!this.webSocketManager || !this.webSocketManager.broadcastToSession) {
|
|
1082
|
-
return;
|
|
1083
|
-
}
|
|
1084
|
-
|
|
1085
|
-
this.webSocketManager.broadcastToSession(sessionId, {
|
|
1086
|
-
type: 'compaction_event',
|
|
1087
|
-
data: {
|
|
1088
|
-
agentId,
|
|
1089
|
-
timestamp: new Date().toISOString(),
|
|
1090
|
-
...data
|
|
1091
|
-
}
|
|
1092
|
-
});
|
|
1093
|
-
}
|
|
1094
|
-
|
|
1095
|
-
/**
|
|
1096
|
-
* Get AI response for agent with proper error handling
|
|
1097
|
-
* @param {string} agentId - Agent ID
|
|
1098
|
-
* @returns {Promise<Object|null>} AI response or null if failed
|
|
1099
|
-
* @private
|
|
1100
|
-
*/
|
|
1101
|
-
async getAgentAIResponse(agentId) {
|
|
1102
|
-
try {
|
|
1103
|
-
const agent = await this.agentPool.getAgent(agentId);
|
|
1104
|
-
if (!agent) return null;
|
|
1105
|
-
|
|
1106
|
-
const conversationHistory = agent.conversations?.full?.messages || [];
|
|
1107
|
-
|
|
1108
|
-
// CRITICAL FIX: Get the session ID from the agent's context in the scheduler
|
|
1109
|
-
const agentContext = this.activeAgents.get(agentId);
|
|
1110
|
-
const sessionId = agentContext?.sessionId || agent.sessionId;
|
|
1111
|
-
|
|
1112
|
-
if (!sessionId) {
|
|
1113
|
-
this.logger.error(`Agent ${agentId} has no session ID - API key resolution will fail`, {
|
|
1114
|
-
agentName: agent.name,
|
|
1115
|
-
hasAgentContext: !!agentContext,
|
|
1116
|
-
agentSessionId: agent.sessionId,
|
|
1117
|
-
contextSessionId: agentContext?.sessionId
|
|
1118
|
-
});
|
|
1119
|
-
// Return null to avoid making requests that will fail
|
|
1120
|
-
return null;
|
|
1121
|
-
}
|
|
1122
|
-
|
|
1123
|
-
// DYNAMIC ROUTING: Check if agent has dynamic model routing enabled
|
|
1124
|
-
let targetModel = agent.currentModel;
|
|
1125
|
-
|
|
1126
|
-
// DEFENSIVE: Ensure targetModel is set, fallback to preferredModel if currentModel is undefined
|
|
1127
|
-
if (!targetModel) {
|
|
1128
|
-
this.logger.warn(`Agent ${agentId} has no currentModel set, using preferredModel as fallback`, {
|
|
1129
|
-
agentId,
|
|
1130
|
-
preferredModel: agent.preferredModel,
|
|
1131
|
-
availableConversations: Object.keys(agent.conversations || {})
|
|
1132
|
-
});
|
|
1133
|
-
|
|
1134
|
-
// Notify user via WebSocket
|
|
1135
|
-
if (this.webSocketManager && sessionId) {
|
|
1136
|
-
this.webSocketManager.broadcastToSession(sessionId, {
|
|
1137
|
-
type: 'agent_warning',
|
|
1138
|
-
agentId,
|
|
1139
|
-
agentName: agent.name,
|
|
1140
|
-
message: 'Agent model configuration restored',
|
|
1141
|
-
details: `Agent "${agent.name}" had no currentModel set. Automatically restored to ${agent.preferredModel || 'default model'}.`,
|
|
1142
|
-
severity: 'warning',
|
|
1143
|
-
timestamp: new Date().toISOString()
|
|
1144
|
-
});
|
|
1145
|
-
}
|
|
1146
|
-
|
|
1147
|
-
targetModel = agent.preferredModel;
|
|
1148
|
-
|
|
1149
|
-
// Update agent's currentModel to preferredModel for future iterations
|
|
1150
|
-
if (targetModel) {
|
|
1151
|
-
agent.currentModel = targetModel;
|
|
1152
|
-
await this.agentPool.persistAgentState(agentId);
|
|
1153
|
-
this.logger.info(`Set agent currentModel to ${targetModel}`);
|
|
1154
|
-
} else {
|
|
1155
|
-
this.logger.error(`Agent ${agentId} has no preferredModel or currentModel, cannot continue`);
|
|
1156
|
-
|
|
1157
|
-
// Notify user of critical error
|
|
1158
|
-
if (this.webSocketManager && sessionId) {
|
|
1159
|
-
this.webSocketManager.broadcastToSession(sessionId, {
|
|
1160
|
-
type: 'agent_error',
|
|
1161
|
-
agentId,
|
|
1162
|
-
agentName: agent.name,
|
|
1163
|
-
message: 'Agent model configuration error',
|
|
1164
|
-
details: `Agent "${agent.name}" has no valid model configuration. Cannot process messages.`,
|
|
1165
|
-
severity: 'error',
|
|
1166
|
-
timestamp: new Date().toISOString()
|
|
1167
|
-
});
|
|
1168
|
-
}
|
|
1169
|
-
|
|
1170
|
-
return null;
|
|
1171
|
-
}
|
|
1172
|
-
}
|
|
1173
|
-
|
|
1174
|
-
if (agent.dynamicModelRouting && this.modelRouterService) {
|
|
1175
|
-
try {
|
|
1176
|
-
// Get the last user message for routing decision
|
|
1177
|
-
const lastUserMessage = [...conversationHistory].reverse().find(m => m.role === 'user');
|
|
1178
|
-
|
|
1179
|
-
if (lastUserMessage) {
|
|
1180
|
-
// Get available models from ModelsService
|
|
1181
|
-
let availableModels = [];
|
|
1182
|
-
if (this.modelsService) {
|
|
1183
|
-
try {
|
|
1184
|
-
this.logger.debug('ModelsService type check', {
|
|
1185
|
-
hasModelsService: !!this.modelsService,
|
|
1186
|
-
type: typeof this.modelsService,
|
|
1187
|
-
methods: Object.getOwnPropertyNames(Object.getPrototypeOf(this.modelsService))
|
|
1188
|
-
});
|
|
1189
|
-
|
|
1190
|
-
// Try to get models, if empty/stale, fetch with current sessionId
|
|
1191
|
-
let allModels = this.modelsService.getModels();
|
|
1192
|
-
|
|
1193
|
-
// Check if models need refresh (safer check)
|
|
1194
|
-
const needsRefresh = !this.modelsService.lastFetched ||
|
|
1195
|
-
(this.modelsService.lastFetched &&
|
|
1196
|
-
(Date.now() - new Date(this.modelsService.lastFetched).getTime()) > (5 * 60 * 1000));
|
|
1197
|
-
|
|
1198
|
-
if (!allModels || allModels.length === 0 || needsRefresh) {
|
|
1199
|
-
this.logger.info('Models list empty or stale, fetching from backend with sessionId');
|
|
1200
|
-
await this.modelsService.fetchModels({ sessionId });
|
|
1201
|
-
allModels = this.modelsService.getModels();
|
|
1202
|
-
}
|
|
1203
|
-
|
|
1204
|
-
// Filter to only include models that are available (not router models)
|
|
1205
|
-
availableModels = allModels
|
|
1206
|
-
.filter(model => model.id !== 'autopilot-model-router' && model.name !== 'autopilot-model-router')
|
|
1207
|
-
.map(model => model.id || model.name);
|
|
1208
|
-
|
|
1209
|
-
this.logger.debug(`Available models for routing: ${availableModels.join(', ')}`);
|
|
1210
|
-
} catch (error) {
|
|
1211
|
-
this.logger.warn(`Failed to get available models for routing: ${error.message}`);
|
|
1212
|
-
}
|
|
1213
|
-
}
|
|
1214
|
-
|
|
1215
|
-
const routingResult = await this.modelRouterService.routeMessage(
|
|
1216
|
-
lastUserMessage.content,
|
|
1217
|
-
conversationHistory.slice(-5), // Last 5 messages for context
|
|
1218
|
-
agent.currentModel,
|
|
1219
|
-
availableModels, // Pass actual available models
|
|
1220
|
-
{ agentId, sessionId }
|
|
1221
|
-
);
|
|
1222
|
-
|
|
1223
|
-
this.logger.info('Routing result analysis', {
|
|
1224
|
-
selectedModel: routingResult.selectedModel,
|
|
1225
|
-
currentModel: agent.currentModel,
|
|
1226
|
-
areEqual: routingResult.selectedModel === agent.currentModel,
|
|
1227
|
-
willSwitch: routingResult.selectedModel && routingResult.selectedModel !== agent.currentModel
|
|
1228
|
-
});
|
|
1229
|
-
|
|
1230
|
-
if (routingResult.selectedModel && routingResult.selectedModel !== agent.currentModel) {
|
|
1231
|
-
this.logger.info(`Dynamic routing: switching from ${agent.currentModel} to ${routingResult.selectedModel}`, {
|
|
1232
|
-
agentId,
|
|
1233
|
-
reason: routingResult.reasoning
|
|
1234
|
-
});
|
|
1235
|
-
|
|
1236
|
-
targetModel = routingResult.selectedModel;
|
|
1237
|
-
|
|
1238
|
-
// Update agent's current model
|
|
1239
|
-
agent.currentModel = targetModel;
|
|
1240
|
-
await this.agentPool.persistAgentState(agentId);
|
|
1241
|
-
|
|
1242
|
-
this.logger.info(`Model updated: targetModel=${targetModel}, agent.currentModel=${agent.currentModel}`);
|
|
1243
|
-
} else {
|
|
1244
|
-
this.logger.info('No model switch needed', {
|
|
1245
|
-
selectedModel: routingResult.selectedModel,
|
|
1246
|
-
currentModel: agent.currentModel,
|
|
1247
|
-
hasSelectedModel: !!routingResult.selectedModel
|
|
1248
|
-
});
|
|
1249
|
-
}
|
|
1250
|
-
}
|
|
1251
|
-
} catch (routingError) {
|
|
1252
|
-
this.logger.warn(`Dynamic routing failed, using current model: ${routingError.message}`);
|
|
1253
|
-
// Fall back to current model on routing failure
|
|
1254
|
-
}
|
|
1255
|
-
}
|
|
1256
|
-
|
|
1257
|
-
this.logger.info(`About to send message to model: ${targetModel}`, {
|
|
1258
|
-
agentId,
|
|
1259
|
-
targetModel,
|
|
1260
|
-
originalModel: agent.currentModel
|
|
1261
|
-
});
|
|
1262
|
-
|
|
1263
|
-
// PHASE 4: Check and perform compaction if needed BEFORE sending to AI
|
|
1264
|
-
const compactionResult = await this.checkAndPerformCompaction(agentId, targetModel, sessionId);
|
|
1265
|
-
|
|
1266
|
-
if (!compactionResult.shouldContinue) {
|
|
1267
|
-
this.logger.warn(`Compaction check returned shouldContinue=false for agent ${agentId}`);
|
|
1268
|
-
return null;
|
|
1269
|
-
}
|
|
1270
|
-
|
|
1271
|
-
if (compactionResult.compactionPerformed) {
|
|
1272
|
-
this.logger.info(`Compaction performed for agent ${agentId}, proceeding with AI request`);
|
|
1273
|
-
}
|
|
1274
|
-
|
|
1275
|
-
// After compaction, retrieve messages from AgentPool (will use compacted if available)
|
|
1276
|
-
const messagesToSend = await this.agentPool.getMessagesForAI(agentId, targetModel);
|
|
1277
|
-
|
|
1278
|
-
// Inject TaskManager instructions for AGENT mode
|
|
1279
|
-
let enhancedSystemPrompt = agent.systemPrompt;
|
|
1280
|
-
if (agent.mode === AGENT_MODES.AGENT) {
|
|
1281
|
-
const taskManagerInstruction = "\n\nIMPORTANT: You are in AGENT mode. The use of TaskManager tool is mandatory. Always create and update tasks to track your work progress. Update the user about task-list status periodically. Use the jobdone tool when your main task is complete.";
|
|
1282
|
-
enhancedSystemPrompt = (agent.systemPrompt || '') + taskManagerInstruction;
|
|
1283
|
-
}
|
|
1284
|
-
|
|
1285
|
-
// Inject dynamic file attachment context
|
|
1286
|
-
try {
|
|
1287
|
-
const fileAttachmentContext = await this.contextInjectionService.buildDynamicContext(agentId);
|
|
1288
|
-
if (fileAttachmentContext) {
|
|
1289
|
-
enhancedSystemPrompt = (enhancedSystemPrompt || '') + fileAttachmentContext;
|
|
1290
|
-
this.logger.debug(`Injected file attachment context for agent ${agentId}`, {
|
|
1291
|
-
contextLength: fileAttachmentContext.length
|
|
1292
|
-
});
|
|
1293
|
-
}
|
|
1294
|
-
} catch (error) {
|
|
1295
|
-
this.logger.warn(`Failed to inject file attachment context for agent ${agentId}`, {
|
|
1296
|
-
error: error.message
|
|
1297
|
-
});
|
|
1298
|
-
// Continue without file attachments if service fails
|
|
1299
|
-
}
|
|
1300
|
-
|
|
1301
|
-
const response = await this.aiService.sendMessage(
|
|
1302
|
-
targetModel,
|
|
1303
|
-
messagesToSend,
|
|
1304
|
-
{
|
|
1305
|
-
agentId: agentId,
|
|
1306
|
-
systemPrompt: enhancedSystemPrompt,
|
|
1307
|
-
sessionId: sessionId,
|
|
1308
|
-
platformProvided: agent.platformProvided
|
|
1309
|
-
}
|
|
1310
|
-
);
|
|
1311
|
-
|
|
1312
|
-
return response;
|
|
1313
|
-
|
|
1314
|
-
} catch (error) {
|
|
1315
|
-
this.logger.error(`AI response failed for agent ${agentId}:`, error);
|
|
1316
|
-
|
|
1317
|
-
// Handle different types of AI service failures
|
|
1318
|
-
await this.handleAIServiceFailure(agentId, error);
|
|
1319
|
-
|
|
1320
|
-
return null;
|
|
1321
|
-
}
|
|
1322
|
-
}
|
|
1323
|
-
|
|
1324
|
-
/**
|
|
1325
|
-
* Handle AI service failures with appropriate recovery strategies
|
|
1326
|
-
* @param {string} agentId - Agent ID that failed
|
|
1327
|
-
* @param {Error} error - The error that occurred
|
|
1328
|
-
* @private
|
|
1329
|
-
*/
|
|
1330
|
-
async handleAIServiceFailure(agentId, error) {
|
|
1331
|
-
const agent = await this.agentPool.getAgent(agentId);
|
|
1332
|
-
if (!agent) return;
|
|
1333
|
-
|
|
1334
|
-
// Determine failure type and response
|
|
1335
|
-
const errorMessage = error.message?.toLowerCase() || '';
|
|
1336
|
-
|
|
1337
|
-
if (errorMessage.includes('api key') || errorMessage.includes('authentication')) {
|
|
1338
|
-
// API key issues - pause agent to prevent infinite retries
|
|
1339
|
-
this.logger.warn(`Agent ${agentId} paused due to API key issue`);
|
|
1340
|
-
|
|
1341
|
-
agent.delayEndTime = new Date(Date.now() + 5 * 60 * 1000).toISOString(); // 5 minute delay
|
|
1342
|
-
await this.agentPool.persistAgentState(agentId);
|
|
1343
|
-
|
|
1344
|
-
// Add error message to agent's queue
|
|
1345
|
-
await this.agentPool.addToolResult(agentId, {
|
|
1346
|
-
toolId: 'system-error',
|
|
1347
|
-
status: 'failed',
|
|
1348
|
-
error: 'API key authentication failed. Please check your API key configuration in Settings.',
|
|
1349
|
-
timestamp: new Date().toISOString()
|
|
1350
|
-
});
|
|
1351
|
-
|
|
1352
|
-
} else if (errorMessage.includes('rate limit') || errorMessage.includes('too many requests')) {
|
|
1353
|
-
// Rate limit - delay agent
|
|
1354
|
-
this.logger.warn(`Agent ${agentId} delayed due to rate limiting`);
|
|
1355
|
-
|
|
1356
|
-
agent.delayEndTime = new Date(Date.now() + 2 * 60 * 1000).toISOString(); // 2 minute delay
|
|
1357
|
-
await this.agentPool.persistAgentState(agentId);
|
|
1358
|
-
|
|
1359
|
-
} else if (errorMessage.includes('timeout') || errorMessage.includes('network')) {
|
|
1360
|
-
// Network issues - shorter delay and retry
|
|
1361
|
-
this.logger.warn(`Agent ${agentId} delayed due to network issues`);
|
|
1362
|
-
|
|
1363
|
-
agent.delayEndTime = new Date(Date.now() + 30 * 1000).toISOString(); // 30 second delay
|
|
1364
|
-
await this.agentPool.persistAgentState(agentId);
|
|
1365
|
-
|
|
1366
|
-
} else {
|
|
1367
|
-
// Unknown error - pause agent and notify
|
|
1368
|
-
this.logger.error(`Agent ${agentId} paused due to unknown AI service error: ${error.message}`);
|
|
1369
|
-
|
|
1370
|
-
agent.delayEndTime = new Date(Date.now() + 1 * 60 * 1000).toISOString(); // 1 minute delay
|
|
1371
|
-
await this.agentPool.persistAgentState(agentId);
|
|
1372
|
-
|
|
1373
|
-
// Add error message to agent's queue
|
|
1374
|
-
await this.agentPool.addToolResult(agentId, {
|
|
1375
|
-
toolId: 'system-error',
|
|
1376
|
-
status: 'failed',
|
|
1377
|
-
error: `AI service error: ${error.message}. Agent temporarily paused.`,
|
|
1378
|
-
timestamp: new Date().toISOString()
|
|
1379
|
-
});
|
|
1380
|
-
}
|
|
1381
|
-
|
|
1382
|
-
// Broadcast error to UI
|
|
1383
|
-
if (this.webSocketManager && this.webSocketManager.broadcastToSession) {
|
|
1384
|
-
const agentContext = this.activeAgents.get(agentId);
|
|
1385
|
-
const sessionId = agentContext?.sessionId || 'scheduler-session';
|
|
1386
|
-
|
|
1387
|
-
// FIX: Wrap payload in 'data' field to match UI expectations
|
|
1388
|
-
this.webSocketManager.broadcastToSession(sessionId, {
|
|
1389
|
-
type: 'agent_error',
|
|
1390
|
-
data: {
|
|
1391
|
-
agentId: agentId,
|
|
1392
|
-
error: error.message,
|
|
1393
|
-
recovery: 'Agent temporarily paused for recovery',
|
|
1394
|
-
timestamp: new Date().toISOString()
|
|
1395
|
-
}
|
|
1396
|
-
});
|
|
1397
|
-
}
|
|
1398
|
-
}
|
|
1399
|
-
|
|
1400
|
-
/**
|
|
1401
|
-
* Process AI response and execute any tools
|
|
1402
|
-
* @param {string} agentId - Agent ID
|
|
1403
|
-
* @param {Object} aiResponse - AI service response
|
|
1404
|
-
* @private
|
|
1405
|
-
*/
|
|
1406
|
-
async processAIResponse(agentId, aiResponse) {
|
|
1407
|
-
// Get the session ID from the agent's context BEFORE it might be removed
|
|
1408
|
-
const agentContext = this.activeAgents.get(agentId);
|
|
1409
|
-
const sessionId = agentContext?.sessionId || 'scheduler-session';
|
|
1410
|
-
|
|
1411
|
-
// Add AI response to conversation (don't broadcast yet - wait for tool processing)
|
|
1412
|
-
const responseMessage = {
|
|
1413
|
-
id: `ai-response-${Date.now()}`,
|
|
1414
|
-
agentId: agentId,
|
|
1415
|
-
role: MESSAGE_ROLES.ASSISTANT,
|
|
1416
|
-
content: aiResponse.content,
|
|
1417
|
-
timestamp: new Date().toISOString(),
|
|
1418
|
-
model: aiResponse.model,
|
|
1419
|
-
tokenUsage: aiResponse.tokenUsage,
|
|
1420
|
-
sessionId: sessionId // CRITICAL: Store sessionId in message for later broadcast
|
|
1421
|
-
};
|
|
1422
|
-
|
|
1423
|
-
await this.addMessageToConversation(agentId, responseMessage, false);
|
|
1424
|
-
|
|
1425
|
-
// Extract and execute tools using MessageProcessor
|
|
1426
|
-
let toolExecutions = [];
|
|
1427
|
-
try {
|
|
1428
|
-
|
|
1429
|
-
const toolResults = await this.messageProcessor.extractAndExecuteTools(
|
|
1430
|
-
aiResponse.content,
|
|
1431
|
-
agentId,
|
|
1432
|
-
{ sessionId: sessionId }
|
|
1433
|
-
);
|
|
1434
|
-
|
|
1435
|
-
// Queue tool results in T queue for next iteration
|
|
1436
|
-
if (toolResults.length > 0) {
|
|
1437
|
-
const agent = await this.agentPool.getAgent(agentId);
|
|
1438
|
-
if (agent) {
|
|
1439
|
-
for (const result of toolResults) {
|
|
1440
|
-
agent.messageQueues.toolResults.push({
|
|
1441
|
-
id: `tool-result-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
|
|
1442
|
-
toolId: result.toolId,
|
|
1443
|
-
status: result.status,
|
|
1444
|
-
result: result.result,
|
|
1445
|
-
error: result.error,
|
|
1446
|
-
executionTime: result.executionTime,
|
|
1447
|
-
timestamp: new Date().toISOString(),
|
|
1448
|
-
queuedAt: new Date().toISOString()
|
|
1449
|
-
});
|
|
1450
|
-
|
|
1451
|
-
// Collect tool execution info for UI display
|
|
1452
|
-
toolExecutions.push({
|
|
1453
|
-
toolId: result.toolId,
|
|
1454
|
-
status: result.status,
|
|
1455
|
-
error: result.error,
|
|
1456
|
-
executionTime: result.executionTime
|
|
1457
|
-
});
|
|
1458
|
-
}
|
|
1459
|
-
|
|
1460
|
-
await this.agentPool.persistAgentState(agentId);
|
|
1461
|
-
}
|
|
1462
|
-
}
|
|
1463
|
-
|
|
1464
|
-
} catch (error) {
|
|
1465
|
-
this.logger.error(`Tool execution failed for agent ${agentId}:`, error);
|
|
1466
|
-
}
|
|
1467
|
-
|
|
1468
|
-
// Add tool execution info to response message for UI
|
|
1469
|
-
if (toolExecutions.length > 0) {
|
|
1470
|
-
responseMessage.toolExecutions = toolExecutions;
|
|
1471
|
-
responseMessage.hasToolExecutions = true;
|
|
1472
|
-
}
|
|
1473
|
-
|
|
1474
|
-
// Broadcast the final AI response to UI after all processing
|
|
1475
|
-
if (this.shouldBroadcastMessage(responseMessage)) {
|
|
1476
|
-
// Get updated agent info for UI sync
|
|
1477
|
-
const updatedAgent = await this.agentPool.getAgent(agentId);
|
|
1478
|
-
|
|
1479
|
-
// Broadcast with agent's current model (may have changed due to dynamic routing)
|
|
1480
|
-
this.broadcastMessageUpdate(agentId, responseMessage, {
|
|
1481
|
-
agentCurrentModel: updatedAgent?.currentModel
|
|
1482
|
-
});
|
|
1483
|
-
}
|
|
1484
|
-
}
|
|
1485
|
-
|
|
1486
|
-
/**
|
|
1487
|
-
* Determine if agent should continue in scheduler
|
|
1488
|
-
* @param {string} agentId - Agent ID
|
|
1489
|
-
* @param {Object} agent - Agent object
|
|
1490
|
-
* @returns {boolean} Whether agent should continue
|
|
1491
|
-
* @private
|
|
1492
|
-
*/
|
|
1493
|
-
shouldAgentContinue(agentId, agent) {
|
|
1494
|
-
if (!agent) return false;
|
|
1495
|
-
|
|
1496
|
-
// Check for jobdone tool execution
|
|
1497
|
-
const hasJobDone = agent.messageQueues.toolResults.some(result =>
|
|
1498
|
-
result.toolId === 'jobdone' ||
|
|
1499
|
-
(result.result && String(result.result).toLowerCase().includes('task completed'))
|
|
1500
|
-
);
|
|
1501
|
-
|
|
1502
|
-
if (hasJobDone) {
|
|
1503
|
-
this.logger.info(`Agent ${agentId} executed jobdone - removing from scheduler`);
|
|
1504
|
-
return false;
|
|
1505
|
-
}
|
|
1506
|
-
|
|
1507
|
-
// CHAT agents are removed after processing messages
|
|
1508
|
-
// CRITICAL FIX: Only continue if there are NEW user messages or inter-agent messages
|
|
1509
|
-
// Tool results should NOT keep CHAT agents in scheduler
|
|
1510
|
-
if (agent.mode === AGENT_MODES.CHAT) {
|
|
1511
|
-
const hasNewMessages = agent.messageQueues.userMessages.length > 0 ||
|
|
1512
|
-
agent.messageQueues.interAgentMessages.length > 0;
|
|
1513
|
-
|
|
1514
|
-
if (!hasNewMessages) {
|
|
1515
|
-
this.logger.debug(`CHAT agent ${agentId} has no new messages - removing from scheduler`, {
|
|
1516
|
-
toolResults: agent.messageQueues.toolResults.length,
|
|
1517
|
-
userMessages: agent.messageQueues.userMessages.length,
|
|
1518
|
-
interAgentMessages: agent.messageQueues.interAgentMessages.length
|
|
1519
|
-
});
|
|
1520
|
-
}
|
|
1521
|
-
|
|
1522
|
-
return hasNewMessages; // Only continue if there are NEW messages, not tool results
|
|
1523
|
-
}
|
|
1524
|
-
|
|
1525
|
-
// AGENT agents continue until jobdone
|
|
1526
|
-
if (agent.mode === AGENT_MODES.AGENT) {
|
|
1527
|
-
return !agent.stopRequested;
|
|
1528
|
-
}
|
|
1529
|
-
|
|
1530
|
-
return false;
|
|
1531
|
-
}
|
|
1532
|
-
|
|
1533
|
-
/**
|
|
1534
|
-
* Format tool result for conversation
|
|
1535
|
-
* @param {Object} toolResult - Tool result message
|
|
1536
|
-
* @returns {string} Formatted content
|
|
1537
|
-
* @private
|
|
1538
|
-
*/
|
|
1539
|
-
formatToolResult(toolResult) {
|
|
1540
|
-
if (toolResult.status === 'completed') {
|
|
1541
|
-
if (typeof toolResult.result === 'object') {
|
|
1542
|
-
return JSON.stringify(toolResult.result, null, 2);
|
|
1543
|
-
}
|
|
1544
|
-
return String(toolResult.result || 'Tool executed successfully');
|
|
1545
|
-
} else if (toolResult.status === 'failed') {
|
|
1546
|
-
return `Tool execution failed: ${toolResult.error || 'Unknown error'}`;
|
|
1547
|
-
}
|
|
1548
|
-
return `Tool status: ${toolResult.status}`;
|
|
1549
|
-
}
|
|
1550
|
-
|
|
1551
|
-
/**
|
|
1552
|
-
* Check if message should be broadcast to UI
|
|
1553
|
-
* @param {Object} message - Message to check
|
|
1554
|
-
* @returns {boolean} Whether to broadcast
|
|
1555
|
-
* @private
|
|
1556
|
-
*/
|
|
1557
|
-
shouldBroadcastMessage(message) {
|
|
1558
|
-
// Don't broadcast internal scheduler prompts
|
|
1559
|
-
if (message.type === 'scheduler-prompt') {
|
|
1560
|
-
return false;
|
|
1561
|
-
}
|
|
1562
|
-
|
|
1563
|
-
// Don't broadcast pure system instructions (but allow system messages from inter-agent communication)
|
|
1564
|
-
if (message.role === MESSAGE_ROLES.SYSTEM && !message.queueType) {
|
|
1565
|
-
return false;
|
|
1566
|
-
}
|
|
1567
|
-
|
|
1568
|
-
// Broadcast all other messages (user, assistant, tool, inter-agent)
|
|
1569
|
-
return true;
|
|
1570
|
-
}
|
|
1571
|
-
|
|
1572
|
-
/**
|
|
1573
|
-
* Broadcast message update to UI
|
|
1574
|
-
* @param {string} agentId - Agent ID
|
|
1575
|
-
* @param {Object} message - Message that was added
|
|
1576
|
-
* @param {Object} agentInfo - Additional agent information for UI sync
|
|
1577
|
-
* @private
|
|
1578
|
-
*/
|
|
1579
|
-
broadcastMessageUpdate(agentId, message, agentInfo = {}) {
|
|
1580
|
-
if (this.webSocketManager && this.webSocketManager.broadcastToSession) {
|
|
1581
|
-
// Get the session ID from the agent's context or the message itself
|
|
1582
|
-
const agentContext = this.activeAgents.get(agentId);
|
|
1583
|
-
let sessionId = agentContext?.sessionId;
|
|
1584
|
-
|
|
1585
|
-
// CRITICAL FIX: If no context (agent already removed), try to get sessionId from message
|
|
1586
|
-
if (!sessionId && message.sessionId) {
|
|
1587
|
-
sessionId = message.sessionId;
|
|
1588
|
-
}
|
|
1589
|
-
|
|
1590
|
-
// Final fallback
|
|
1591
|
-
if (!sessionId) {
|
|
1592
|
-
sessionId = 'scheduler-session';
|
|
1593
|
-
}
|
|
1594
|
-
|
|
1595
|
-
// DEBUG: Log session ID mapping
|
|
1596
|
-
this.logger.info('Broadcasting message to session', {
|
|
1597
|
-
agentId: agentId,
|
|
1598
|
-
sessionId: sessionId,
|
|
1599
|
-
hasAgentContext: !!agentContext,
|
|
1600
|
-
agentContextSessionId: agentContext?.sessionId,
|
|
1601
|
-
messageSessionId: message.sessionId,
|
|
1602
|
-
messageRole: message.role,
|
|
1603
|
-
messageType: message.type
|
|
1604
|
-
});
|
|
1605
|
-
|
|
1606
|
-
// FIX: Wrap payload in 'data' field to match UI expectations
|
|
1607
|
-
this.webSocketManager.broadcastToSession(sessionId, {
|
|
1608
|
-
type: 'message_added',
|
|
1609
|
-
data: {
|
|
1610
|
-
agentId: agentId,
|
|
1611
|
-
message: message,
|
|
1612
|
-
timestamp: new Date().toISOString(),
|
|
1613
|
-
// Include agent current model for UI updates after dynamic routing
|
|
1614
|
-
agentCurrentModel: agentInfo.agentCurrentModel
|
|
1615
|
-
}
|
|
1616
|
-
});
|
|
1617
|
-
}
|
|
1618
|
-
}
|
|
1619
|
-
|
|
1620
|
-
/**
|
|
1621
|
-
* Check if agent has pending tasks
|
|
1622
|
-
* @param {Object} agent - Agent object
|
|
1623
|
-
* @returns {boolean} Whether agent has pending tasks
|
|
1624
|
-
* @private
|
|
1625
|
-
*/
|
|
1626
|
-
hasPendingTasks(agent) {
|
|
1627
|
-
if (!agent.taskList || !agent.taskList.tasks) {
|
|
1628
|
-
return false;
|
|
1629
|
-
}
|
|
1630
|
-
|
|
1631
|
-
// Check for pending or in_progress tasks
|
|
1632
|
-
return agent.taskList.tasks.some(task =>
|
|
1633
|
-
task.status === 'pending' || task.status === 'in_progress'
|
|
1634
|
-
);
|
|
1635
|
-
}
|
|
1636
|
-
|
|
1637
|
-
/**
|
|
1638
|
-
* Check if agent has unprocessed messages (for task creation)
|
|
1639
|
-
* @param {Object} agent - Agent object
|
|
1640
|
-
* @returns {boolean} Whether agent has unprocessed messages
|
|
1641
|
-
* @private
|
|
1642
|
-
*/
|
|
1643
|
-
hasUnprocessedMessages(agent) {
|
|
1644
|
-
// Check for incoming messages that should trigger task creation
|
|
1645
|
-
if (agent.incomingMessages && agent.incomingMessages.length > 0) {
|
|
1646
|
-
return true;
|
|
1647
|
-
}
|
|
1648
|
-
|
|
1649
|
-
// Check for recent inter-agent communication that might need follow-up
|
|
1650
|
-
if (agent.interAgentTracking && agent.interAgentTracking.size > 0) {
|
|
1651
|
-
const now = Date.now();
|
|
1652
|
-
const RECENT_MESSAGE_THRESHOLD = 10 * 60 * 1000; // 10 minutes
|
|
1653
|
-
|
|
1654
|
-
for (const tracking of agent.interAgentTracking.values()) {
|
|
1655
|
-
if (tracking.lastReceived &&
|
|
1656
|
-
(now - tracking.lastReceived) < RECENT_MESSAGE_THRESHOLD &&
|
|
1657
|
-
tracking.lastType === 'received') {
|
|
1658
|
-
return true;
|
|
1659
|
-
}
|
|
1660
|
-
}
|
|
1661
|
-
}
|
|
1662
|
-
|
|
1663
|
-
return false;
|
|
1664
|
-
}
|
|
1665
|
-
|
|
1666
|
-
/**
|
|
1667
|
-
* Auto-create initial task if agent just switched to AGENT mode
|
|
1668
|
-
* @param {string} agentId - Agent ID
|
|
1669
|
-
* @private
|
|
1670
|
-
*/
|
|
1671
|
-
async autoCreateInitialTaskIfNeeded(agentId) {
|
|
1672
|
-
try {
|
|
1673
|
-
const agent = await this.agentPool.getAgent(agentId);
|
|
1674
|
-
if (!agent || agent.mode !== AGENT_MODES.AGENT) {
|
|
1675
|
-
return;
|
|
1676
|
-
}
|
|
1677
|
-
|
|
1678
|
-
// Ensure taskList exists
|
|
1679
|
-
if (!agent.taskList) {
|
|
1680
|
-
agent.taskList = {
|
|
1681
|
-
tasks: [],
|
|
1682
|
-
lastUpdated: new Date().toISOString()
|
|
1683
|
-
};
|
|
1684
|
-
}
|
|
1685
|
-
|
|
1686
|
-
// Check if we already have tasks
|
|
1687
|
-
if (agent.taskList.tasks && agent.taskList.tasks.length > 0) {
|
|
1688
|
-
return; // Already has tasks
|
|
1689
|
-
}
|
|
1690
|
-
|
|
1691
|
-
// Look for the last user message in conversation history
|
|
1692
|
-
const conversations = agent.conversations?.full?.messages || [];
|
|
1693
|
-
const lastUserMessage = [...conversations].reverse().find(m => m.role === MESSAGE_ROLES.USER);
|
|
1694
|
-
|
|
1695
|
-
if (lastUserMessage) {
|
|
1696
|
-
const taskTitle = `Process initial request: ${this.extractTaskTitle(lastUserMessage.content)}`;
|
|
1697
|
-
const taskDescription = `Handle user request: "${this.truncateContent(lastUserMessage.content, 200)}"`;
|
|
1698
|
-
|
|
1699
|
-
const task = {
|
|
1700
|
-
id: `task-initial-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
|
|
1701
|
-
title: taskTitle,
|
|
1702
|
-
description: taskDescription,
|
|
1703
|
-
status: 'pending',
|
|
1704
|
-
priority: 'high',
|
|
1705
|
-
createdAt: new Date().toISOString(),
|
|
1706
|
-
updatedAt: new Date().toISOString(),
|
|
1707
|
-
source: 'auto-created-initial',
|
|
1708
|
-
messageId: lastUserMessage.id
|
|
1709
|
-
};
|
|
1710
|
-
|
|
1711
|
-
agent.taskList.tasks.push(task);
|
|
1712
|
-
agent.taskList.lastUpdated = new Date().toISOString();
|
|
1713
|
-
|
|
1714
|
-
await this.agentPool.persistAgentState(agentId);
|
|
1715
|
-
|
|
1716
|
-
this.logger.info(`Auto-created initial task for agent ${agentId}`, {
|
|
1717
|
-
taskId: task.id,
|
|
1718
|
-
title: task.title,
|
|
1719
|
-
agentName: agent.name
|
|
1720
|
-
});
|
|
1721
|
-
}
|
|
1722
|
-
} catch (error) {
|
|
1723
|
-
this.logger.error(`Failed to auto-create initial task for agent ${agentId}`, {
|
|
1724
|
-
error: error.message
|
|
1725
|
-
});
|
|
1726
|
-
}
|
|
1727
|
-
}
|
|
1728
|
-
|
|
1729
|
-
/**
|
|
1730
|
-
* Auto-create tasks for incoming messages (Phase 2)
|
|
1731
|
-
* @param {string} agentId - Agent ID
|
|
1732
|
-
* @param {Array} userMessages - User messages to process
|
|
1733
|
-
* @param {Array} interAgentMessages - Inter-agent messages to process
|
|
1734
|
-
* @private
|
|
1735
|
-
*/
|
|
1736
|
-
async autoCreateTasksForMessages(agentId, userMessages, interAgentMessages) {
|
|
1737
|
-
try {
|
|
1738
|
-
const agent = await this.agentPool.getAgent(agentId);
|
|
1739
|
-
if (!agent || agent.mode !== AGENT_MODES.AGENT) {
|
|
1740
|
-
return; // Only auto-create tasks for AGENT mode agents
|
|
1741
|
-
}
|
|
1742
|
-
|
|
1743
|
-
// Ensure taskList exists
|
|
1744
|
-
if (!agent.taskList) {
|
|
1745
|
-
agent.taskList = {
|
|
1746
|
-
tasks: [],
|
|
1747
|
-
lastUpdated: new Date().toISOString()
|
|
1748
|
-
};
|
|
1749
|
-
}
|
|
1750
|
-
|
|
1751
|
-
// Create tasks for user messages
|
|
1752
|
-
for (const msg of userMessages) {
|
|
1753
|
-
const taskTitle = `Process user request: ${this.extractTaskTitle(msg.content)}`;
|
|
1754
|
-
const taskDescription = `Handle user message: "${this.truncateContent(msg.content, 200)}"`;
|
|
1755
|
-
|
|
1756
|
-
// Check if similar task already exists
|
|
1757
|
-
const existingTask = agent.taskList.tasks.find(task =>
|
|
1758
|
-
task.status === 'pending' &&
|
|
1759
|
-
task.title.includes('Process user request') &&
|
|
1760
|
-
this.calculateContentSimilarity(task.description, taskDescription) > 0.7
|
|
1761
|
-
);
|
|
1762
|
-
|
|
1763
|
-
if (!existingTask) {
|
|
1764
|
-
const task = {
|
|
1765
|
-
id: `task-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
|
|
1766
|
-
title: taskTitle,
|
|
1767
|
-
description: taskDescription,
|
|
1768
|
-
status: 'pending',
|
|
1769
|
-
priority: 'high', // User messages get high priority
|
|
1770
|
-
createdAt: new Date().toISOString(),
|
|
1771
|
-
updatedAt: new Date().toISOString(),
|
|
1772
|
-
source: 'auto-created',
|
|
1773
|
-
messageId: msg.id
|
|
1774
|
-
};
|
|
1775
|
-
|
|
1776
|
-
agent.taskList.tasks.push(task);
|
|
1777
|
-
|
|
1778
|
-
this.logger?.info(`Auto-created task for user message`, {
|
|
1779
|
-
agentId,
|
|
1780
|
-
taskId: task.id,
|
|
1781
|
-
title: task.title
|
|
1782
|
-
});
|
|
1783
|
-
}
|
|
1784
|
-
}
|
|
1785
|
-
|
|
1786
|
-
// Create tasks for inter-agent messages
|
|
1787
|
-
for (const msg of interAgentMessages) {
|
|
1788
|
-
const senderName = msg.senderName || msg.sender || 'Unknown Agent';
|
|
1789
|
-
const taskTitle = `Respond to ${senderName}: ${this.extractTaskTitle(msg.content)}`;
|
|
1790
|
-
const taskDescription = `Handle message from ${senderName}: "${this.truncateContent(msg.content, 200)}"`;
|
|
1791
|
-
|
|
1792
|
-
// Check if similar task already exists
|
|
1793
|
-
const existingTask = agent.taskList.tasks.find(task =>
|
|
1794
|
-
task.status === 'pending' &&
|
|
1795
|
-
task.title.includes(`Respond to ${senderName}`) &&
|
|
1796
|
-
this.calculateContentSimilarity(task.description, taskDescription) > 0.7
|
|
1797
|
-
);
|
|
1798
|
-
|
|
1799
|
-
if (!existingTask) {
|
|
1800
|
-
const task = {
|
|
1801
|
-
id: `task-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
|
|
1802
|
-
title: taskTitle,
|
|
1803
|
-
description: taskDescription,
|
|
1804
|
-
status: 'pending',
|
|
1805
|
-
priority: 'medium', // Inter-agent messages get medium priority
|
|
1806
|
-
createdAt: new Date().toISOString(),
|
|
1807
|
-
updatedAt: new Date().toISOString(),
|
|
1808
|
-
source: 'auto-created',
|
|
1809
|
-
messageId: msg.id,
|
|
1810
|
-
senderAgent: msg.sender
|
|
1811
|
-
};
|
|
1812
|
-
|
|
1813
|
-
agent.taskList.tasks.push(task);
|
|
1814
|
-
|
|
1815
|
-
this.logger?.info(`Auto-created task for inter-agent message`, {
|
|
1816
|
-
agentId,
|
|
1817
|
-
taskId: task.id,
|
|
1818
|
-
title: task.title,
|
|
1819
|
-
sender: senderName
|
|
1820
|
-
});
|
|
1821
|
-
}
|
|
1822
|
-
}
|
|
1823
|
-
|
|
1824
|
-
// Update task list timestamp
|
|
1825
|
-
if (userMessages.length > 0 || interAgentMessages.length > 0) {
|
|
1826
|
-
agent.taskList.lastUpdated = new Date().toISOString();
|
|
1827
|
-
await this.agentPool.persistAgentState(agentId);
|
|
1828
|
-
}
|
|
1829
|
-
|
|
1830
|
-
} catch (error) {
|
|
1831
|
-
this.logger?.error(`Failed to auto-create tasks for agent ${agentId}`, {
|
|
1832
|
-
error: error.message,
|
|
1833
|
-
userMessageCount: userMessages.length,
|
|
1834
|
-
interAgentMessageCount: interAgentMessages.length
|
|
1835
|
-
});
|
|
1836
|
-
}
|
|
1837
|
-
}
|
|
1838
|
-
|
|
1839
|
-
/**
|
|
1840
|
-
* Extract a concise title from message content
|
|
1841
|
-
* @param {string} content - Message content
|
|
1842
|
-
* @returns {string} Extracted title
|
|
1843
|
-
* @private
|
|
1844
|
-
*/
|
|
1845
|
-
extractTaskTitle(content) {
|
|
1846
|
-
// Extract first meaningful sentence or phrase, max 50 chars
|
|
1847
|
-
const cleaned = content.trim().replace(/\n+/g, ' ').replace(/\s+/g, ' ');
|
|
1848
|
-
const firstSentence = cleaned.split(/[.!?]/)[0].trim();
|
|
1849
|
-
|
|
1850
|
-
if (firstSentence.length > 50) {
|
|
1851
|
-
return firstSentence.substring(0, 47) + '...';
|
|
1852
|
-
}
|
|
1853
|
-
|
|
1854
|
-
return firstSentence || 'Process message';
|
|
1855
|
-
}
|
|
1856
|
-
|
|
1857
|
-
/**
|
|
1858
|
-
* Truncate content to specified length
|
|
1859
|
-
* @param {string} content - Content to truncate
|
|
1860
|
-
* @param {number} maxLength - Maximum length
|
|
1861
|
-
* @returns {string} Truncated content
|
|
1862
|
-
* @private
|
|
1863
|
-
*/
|
|
1864
|
-
truncateContent(content, maxLength) {
|
|
1865
|
-
if (content.length <= maxLength) return content;
|
|
1866
|
-
return content.substring(0, maxLength - 3) + '...';
|
|
1867
|
-
}
|
|
1868
|
-
|
|
1869
|
-
/**
|
|
1870
|
-
* Calculate content similarity (simple implementation)
|
|
1871
|
-
* @param {string} content1 - First content
|
|
1872
|
-
* @param {string} content2 - Second content
|
|
1873
|
-
* @returns {number} Similarity score (0-1)
|
|
1874
|
-
* @private
|
|
1875
|
-
*/
|
|
1876
|
-
calculateContentSimilarity(content1, content2) {
|
|
1877
|
-
// Simple word-based similarity
|
|
1878
|
-
const words1 = content1.toLowerCase().split(/\s+/);
|
|
1879
|
-
const words2 = content2.toLowerCase().split(/\s+/);
|
|
1880
|
-
|
|
1881
|
-
const commonWords = words1.filter(word => words2.includes(word));
|
|
1882
|
-
const totalWords = new Set([...words1, ...words2]).size;
|
|
1883
|
-
|
|
1884
|
-
return commonWords.length / totalWords;
|
|
1885
|
-
}
|
|
1886
|
-
|
|
1887
|
-
/**
|
|
1888
|
-
* Auto-mark highest priority pending task as in-progress (Phase 2)
|
|
1889
|
-
* @param {string} agentId - Agent ID
|
|
1890
|
-
* @private
|
|
1891
|
-
*/
|
|
1892
|
-
async autoProgressHighestPriorityTask(agentId) {
|
|
1893
|
-
try {
|
|
1894
|
-
const agent = await this.agentPool.getAgent(agentId);
|
|
1895
|
-
if (!agent || !agent.taskList || !agent.taskList.tasks) {
|
|
1896
|
-
return;
|
|
1897
|
-
}
|
|
1898
|
-
|
|
1899
|
-
// Find highest priority pending task that can be started (respecting dependencies)
|
|
1900
|
-
const priorityOrder = { urgent: 0, high: 1, medium: 2, low: 3 };
|
|
1901
|
-
let pendingTasks = agent.taskList.tasks.filter(task => task.status === 'pending');
|
|
1902
|
-
|
|
1903
|
-
if (pendingTasks.length === 0) {
|
|
1904
|
-
return; // No pending tasks
|
|
1905
|
-
}
|
|
1906
|
-
|
|
1907
|
-
// Phase 3: Filter out blocked tasks (dependencies not met)
|
|
1908
|
-
pendingTasks = this.filterAvailableTasks(agent.taskList.tasks, pendingTasks);
|
|
1909
|
-
|
|
1910
|
-
if (pendingTasks.length === 0) {
|
|
1911
|
-
this.logger?.info(`All pending tasks are blocked by dependencies for agent ${agentId}`);
|
|
1912
|
-
return; // All tasks are blocked
|
|
1913
|
-
}
|
|
1914
|
-
|
|
1915
|
-
// Phase 3.2: Sort by intelligent priority score, fallback to priority level, then creation date
|
|
1916
|
-
pendingTasks.sort((a, b) => {
|
|
1917
|
-
// Use priority score if available (higher score = higher priority)
|
|
1918
|
-
if (a.priorityScore !== undefined && b.priorityScore !== undefined) {
|
|
1919
|
-
const scoreDiff = b.priorityScore - a.priorityScore;
|
|
1920
|
-
if (Math.abs(scoreDiff) > 0.1) return scoreDiff; // Use score if significantly different
|
|
1921
|
-
}
|
|
1922
|
-
|
|
1923
|
-
// Fallback to traditional priority ordering
|
|
1924
|
-
const priorityDiff = priorityOrder[a.priority] - priorityOrder[b.priority];
|
|
1925
|
-
if (priorityDiff !== 0) return priorityDiff;
|
|
1926
|
-
|
|
1927
|
-
// Finally sort by creation date (older first)
|
|
1928
|
-
return new Date(a.createdAt) - new Date(b.createdAt);
|
|
1929
|
-
});
|
|
1930
|
-
|
|
1931
|
-
const taskToProgress = pendingTasks[0];
|
|
1932
|
-
|
|
1933
|
-
// Check if we already have a task in progress
|
|
1934
|
-
const inProgressTasks = agent.taskList.tasks.filter(task => task.status === 'in_progress');
|
|
1935
|
-
|
|
1936
|
-
if (inProgressTasks.length === 0) {
|
|
1937
|
-
// Mark highest priority task as in-progress
|
|
1938
|
-
taskToProgress.status = 'in_progress';
|
|
1939
|
-
taskToProgress.updatedAt = new Date().toISOString();
|
|
1940
|
-
taskToProgress.startedAt = new Date().toISOString();
|
|
1941
|
-
|
|
1942
|
-
agent.taskList.lastUpdated = new Date().toISOString();
|
|
1943
|
-
await this.agentPool.persistAgentState(agentId);
|
|
1944
|
-
|
|
1945
|
-
this.logger?.info(`Auto-progressed task to in-progress`, {
|
|
1946
|
-
agentId,
|
|
1947
|
-
taskId: taskToProgress.id,
|
|
1948
|
-
title: taskToProgress.title,
|
|
1949
|
-
priority: taskToProgress.priority
|
|
1950
|
-
});
|
|
1951
|
-
}
|
|
1952
|
-
|
|
1953
|
-
} catch (error) {
|
|
1954
|
-
this.logger?.error(`Failed to auto-progress task for agent ${agentId}`, {
|
|
1955
|
-
error: error.message
|
|
1956
|
-
});
|
|
1957
|
-
}
|
|
1958
|
-
}
|
|
1959
|
-
|
|
1960
|
-
/**
|
|
1961
|
-
* Filter tasks to only include those that can be started (Phase 3)
|
|
1962
|
-
* @param {Array} allTasks - All tasks for the agent
|
|
1963
|
-
* @param {Array} pendingTasks - Tasks with pending status
|
|
1964
|
-
* @returns {Array} Tasks that can be started (no blocking dependencies)
|
|
1965
|
-
* @private
|
|
1966
|
-
*/
|
|
1967
|
-
filterAvailableTasks(allTasks, pendingTasks) {
|
|
1968
|
-
return pendingTasks.filter(task => {
|
|
1969
|
-
// If task has no dependencies, it's available
|
|
1970
|
-
if (!task.dependencies || task.dependencies.length === 0) {
|
|
1971
|
-
return true;
|
|
1972
|
-
}
|
|
1973
|
-
|
|
1974
|
-
// Check all blocking dependencies
|
|
1975
|
-
const blockingDeps = task.dependencies.filter(dep => dep.type === 'blocks');
|
|
1976
|
-
|
|
1977
|
-
for (const dep of blockingDeps) {
|
|
1978
|
-
const depTask = allTasks.find(t => t.id === dep.taskId);
|
|
1979
|
-
|
|
1980
|
-
// If dependency task doesn't exist or isn't completed, task is blocked
|
|
1981
|
-
if (!depTask || depTask.status !== 'completed') {
|
|
1982
|
-
return false;
|
|
1983
|
-
}
|
|
1984
|
-
}
|
|
1985
|
-
|
|
1986
|
-
return true; // All blocking dependencies are satisfied
|
|
1987
|
-
});
|
|
1988
|
-
}
|
|
1989
|
-
|
|
1990
|
-
/**
|
|
1991
|
-
* Update task statuses based on dependency completion (Phase 3)
|
|
1992
|
-
* @param {Object} agent - Agent object
|
|
1993
|
-
* @param {string} completedTaskId - ID of the task that was just completed
|
|
1994
|
-
* @private
|
|
1995
|
-
*/
|
|
1996
|
-
async updateDependentTasks(agent, completedTaskId) {
|
|
1997
|
-
try {
|
|
1998
|
-
if (!agent.taskList || !agent.taskList.tasks) {
|
|
1999
|
-
return;
|
|
2000
|
-
}
|
|
2001
|
-
|
|
2002
|
-
let updated = false;
|
|
2003
|
-
|
|
2004
|
-
// Find tasks that were blocked by the completed task
|
|
2005
|
-
for (const task of agent.taskList.tasks) {
|
|
2006
|
-
if (task.status === 'blocked' && task.dependencies) {
|
|
2007
|
-
const blockingDep = task.dependencies.find(
|
|
2008
|
-
dep => dep.type === 'blocks' && dep.taskId === completedTaskId
|
|
2009
|
-
);
|
|
2010
|
-
|
|
2011
|
-
if (blockingDep) {
|
|
2012
|
-
// Check if all other blocking dependencies are also completed
|
|
2013
|
-
const stillBlocked = task.dependencies.some(dep => {
|
|
2014
|
-
if (dep.type !== 'blocks') return false;
|
|
2015
|
-
const depTask = agent.taskList.tasks.find(t => t.id === dep.taskId);
|
|
2016
|
-
return depTask && depTask.status !== 'completed';
|
|
2017
|
-
});
|
|
2018
|
-
|
|
2019
|
-
if (!stillBlocked) {
|
|
2020
|
-
task.status = 'pending';
|
|
2021
|
-
task.updatedAt = new Date().toISOString();
|
|
2022
|
-
updated = true;
|
|
2023
|
-
|
|
2024
|
-
this.logger?.info(`Task unblocked due to dependency completion`, {
|
|
2025
|
-
taskId: task.id,
|
|
2026
|
-
title: task.title,
|
|
2027
|
-
completedDependency: completedTaskId
|
|
2028
|
-
});
|
|
2029
|
-
}
|
|
2030
|
-
}
|
|
2031
|
-
}
|
|
2032
|
-
}
|
|
2033
|
-
|
|
2034
|
-
if (updated) {
|
|
2035
|
-
agent.taskList.lastUpdated = new Date().toISOString();
|
|
2036
|
-
await this.agentPool.persistAgentState(agent.id);
|
|
2037
|
-
}
|
|
2038
|
-
|
|
2039
|
-
} catch (error) {
|
|
2040
|
-
this.logger?.error(`Failed to update dependent tasks for agent ${agent.id}`, {
|
|
2041
|
-
error: error.message,
|
|
2042
|
-
completedTaskId
|
|
2043
|
-
});
|
|
2044
|
-
}
|
|
2045
|
-
}
|
|
2046
|
-
|
|
2047
|
-
/**
|
|
2048
|
-
* Generate a hash representing the current agent state
|
|
2049
|
-
* @param {Object} agent - Agent object
|
|
2050
|
-
* @returns {string} Hash of the current state
|
|
2051
|
-
* @private
|
|
2052
|
-
*/
|
|
2053
|
-
generateAgentStateHash(agent) {
|
|
2054
|
-
// Create a string representation of the relevant state
|
|
2055
|
-
const stateComponents = [];
|
|
2056
|
-
|
|
2057
|
-
// CRITICAL FIX: Only include INPUT messages (user and tool), NOT assistant responses
|
|
2058
|
-
// This allows duplicate detection to work when agent generates same response repeatedly
|
|
2059
|
-
// Assistant messages change every iteration, which previously prevented loop detection
|
|
2060
|
-
const allMessages = agent.conversations?.full?.messages || [];
|
|
2061
|
-
const inputMessages = allMessages
|
|
2062
|
-
.filter(m => m.role === 'user' || m.role === 'tool')
|
|
2063
|
-
.slice(-5); // Last 5 input messages for context
|
|
2064
|
-
|
|
2065
|
-
const messagesSummary = inputMessages
|
|
2066
|
-
.map(m => `${m.role}:${m.content?.substring(0, 100)}`)
|
|
2067
|
-
.join('|');
|
|
2068
|
-
stateComponents.push(`msgs:${messagesSummary}`);
|
|
2069
|
-
|
|
2070
|
-
// Include pending and in-progress tasks
|
|
2071
|
-
if (agent.taskList?.tasks) {
|
|
2072
|
-
const activeTasks = agent.taskList.tasks
|
|
2073
|
-
.filter(t => t.status === 'pending' || t.status === 'in_progress')
|
|
2074
|
-
.map(t => `${t.id}:${t.status}`)
|
|
2075
|
-
.sort()
|
|
2076
|
-
.join(',');
|
|
2077
|
-
stateComponents.push(`tasks:${activeTasks}`);
|
|
2078
|
-
}
|
|
2079
|
-
|
|
2080
|
-
// Include queued messages counts
|
|
2081
|
-
const queues = agent.messageQueues || {};
|
|
2082
|
-
stateComponents.push(`queues:T${queues.toolResults?.length || 0}:I${queues.interAgentMessages?.length || 0}:U${queues.userMessages?.length || 0}`);
|
|
2083
|
-
|
|
2084
|
-
// Create a simple hash using string representation
|
|
2085
|
-
// For production, consider using crypto.createHash('sha256')
|
|
2086
|
-
const stateString = stateComponents.join('||');
|
|
2087
|
-
|
|
2088
|
-
// Simple hash function (could be replaced with crypto hash)
|
|
2089
|
-
let hash = 0;
|
|
2090
|
-
for (let i = 0; i < stateString.length; i++) {
|
|
2091
|
-
const char = stateString.charCodeAt(i);
|
|
2092
|
-
hash = ((hash << 5) - hash) + char;
|
|
2093
|
-
hash = hash & hash; // Convert to 32bit integer
|
|
2094
|
-
}
|
|
2095
|
-
|
|
2096
|
-
return `${hash}_${stateString.length}`;
|
|
2097
|
-
}
|
|
2098
|
-
|
|
2099
|
-
/**
|
|
2100
|
-
* Check if this state has already been processed
|
|
2101
|
-
* @param {string} agentId - Agent ID
|
|
2102
|
-
* @param {string} stateHash - State hash to check
|
|
2103
|
-
* @returns {boolean} True if already processed
|
|
2104
|
-
* @private
|
|
2105
|
-
*/
|
|
2106
|
-
hasProcessedState(agentId, stateHash) {
|
|
2107
|
-
const agentHashes = this.processedStateHashes.get(agentId);
|
|
2108
|
-
return agentHashes ? agentHashes.has(stateHash) : false;
|
|
2109
|
-
}
|
|
2110
|
-
|
|
2111
|
-
/**
|
|
2112
|
-
* Mark state as processed
|
|
2113
|
-
* @param {string} agentId - Agent ID
|
|
2114
|
-
* @param {string} stateHash - State hash to mark
|
|
2115
|
-
* @private
|
|
2116
|
-
*/
|
|
2117
|
-
markStateAsProcessed(agentId, stateHash) {
|
|
2118
|
-
if (!this.processedStateHashes.has(agentId)) {
|
|
2119
|
-
this.processedStateHashes.set(agentId, new Set());
|
|
2120
|
-
}
|
|
2121
|
-
|
|
2122
|
-
const agentHashes = this.processedStateHashes.get(agentId);
|
|
2123
|
-
agentHashes.add(stateHash);
|
|
2124
|
-
|
|
2125
|
-
// Limit the size of stored hashes to prevent memory issues
|
|
2126
|
-
if (agentHashes.size > 100) {
|
|
2127
|
-
// Remove oldest entries (convert to array, slice, rebuild set)
|
|
2128
|
-
const hashArray = Array.from(agentHashes);
|
|
2129
|
-
const recentHashes = hashArray.slice(-50); // Keep last 50
|
|
2130
|
-
this.processedStateHashes.set(agentId, new Set(recentHashes));
|
|
2131
|
-
}
|
|
2132
|
-
}
|
|
2133
|
-
|
|
2134
|
-
/**
|
|
2135
|
-
* Get scheduler status
|
|
2136
|
-
* @returns {Object} Scheduler status
|
|
2137
|
-
*/
|
|
2138
|
-
getStatus() {
|
|
2139
|
-
return {
|
|
2140
|
-
isRunning: this.isRunning,
|
|
2141
|
-
activeAgents: Array.from(this.activeAgents),
|
|
2142
|
-
agentCount: this.activeAgents.size
|
|
2143
|
-
};
|
|
2144
|
-
}
|
|
2145
|
-
}
|
|
2146
|
-
|
|
2147
|
-
export default AgentScheduler;
|
|
1
|
+
const a0_0x567dbc=a0_0x2d8a;(function(_0x5ac86a,_0x55144b){const _0x1c2fe1=a0_0x2d8a,_0x2d81ae=_0x5ac86a();while(!![]){try{const _0x3c0ad2=parseInt(_0x1c2fe1(0x115))/0x1*(-parseInt(_0x1c2fe1(0x150))/0x2)+parseInt(_0x1c2fe1(0xd0))/0x3*(parseInt(_0x1c2fe1(0x131))/0x4)+parseInt(_0x1c2fe1(0x1d9))/0x5+-parseInt(_0x1c2fe1(0x158))/0x6*(-parseInt(_0x1c2fe1(0xfd))/0x7)+parseInt(_0x1c2fe1(0x16e))/0x8*(-parseInt(_0x1c2fe1(0x192))/0x9)+-parseInt(_0x1c2fe1(0x16d))/0xa+parseInt(_0x1c2fe1(0x152))/0xb*(parseInt(_0x1c2fe1(0x116))/0xc);if(_0x3c0ad2===_0x55144b)break;else _0x2d81ae['push'](_0x2d81ae['shift']());}catch(_0x1b3525){_0x2d81ae['push'](_0x2d81ae['shift']());}}}(a0_0xfca2,0x26725));import{AGENT_MODES,AGENT_MODE_STATES,MESSAGE_ROLES,COMPACTION_CONFIG,COMPACTION_STATUS,COMPACTION_STRATEGIES,TOKEN_COUNTING_MODES}from'../utilities/constants.js';function a0_0x2d8a(_0x16013c,_0x48eb1f){_0x16013c=_0x16013c-0xc8;const _0xfca2d7=a0_0xfca2();let _0x2d8a69=_0xfca2d7[_0x16013c];if(a0_0x2d8a['qzLPOx']===undefined){var _0x1416f7=function(_0x1b8ba5){const _0x48cbff='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';let _0x59e710='',_0x2b4723='';for(let _0x491e7f=0x0,_0x971094,_0x2b24db,_0x3c8654=0x0;_0x2b24db=_0x1b8ba5['charAt'](_0x3c8654++);~_0x2b24db&&(_0x971094=_0x491e7f%0x4?_0x971094*0x40+_0x2b24db:_0x2b24db,_0x491e7f++%0x4)?_0x59e710+=String['fromCharCode'](0xff&_0x971094>>(-0x2*_0x491e7f&0x6)):0x0){_0x2b24db=_0x48cbff['indexOf'](_0x2b24db);}for(let _0x526966=0x0,_0x31d83b=_0x59e710['length'];_0x526966<_0x31d83b;_0x526966++){_0x2b4723+='%'+('00'+_0x59e710['charCodeAt'](_0x526966)['toString'](0x10))['slice'](-0x2);}return decodeURIComponent(_0x2b4723);};a0_0x2d8a['SPgFTx']=_0x1416f7,a0_0x2d8a['BjhwfS']={},a0_0x2d8a['qzLPOx']=!![];}const _0x5131d3=_0xfca2d7[0x0],_0x5b7510=_0x16013c+_0x5131d3,_0x4cd77d=a0_0x2d8a['BjhwfS'][_0x5b7510];return!_0x4cd77d?(_0x2d8a69=a0_0x2d8a['SPgFTx'](_0x2d8a69),a0_0x2d8a['BjhwfS'][_0x5b7510]=_0x2d8a69):_0x2d8a69=_0x4cd77d,_0x2d8a69;}import a0_0x59e710 from'../services/contextInjectionService.js';import a0_0x2b4723 from'../services/tokenCountingService.js';import a0_0x491e7f from'../services/conversationCompactionService.js';function a0_0xfca2(){const _0x3dd9c0=['Dhj1zq','igHHCYbUBYbWCMvMzxjYzwrnB2rLBcbVCIbJDxjYzw50tw9KzwWSignHBM5VDcbJB250Aw51zq','w0nptvbbq1qTtuvtu0fhrvmTu0vmrunururD','Cgf1C2vK','nZe4otrfr0rzy1u','Dg9Vig1HBNKGCMvXDwvZDhm','ntm2mdqXwu1zzeH5','BgfZDfvWzgf0zwq','C3rVCfjLCxvLC3rLza','CxvLDwvKqxq','zxHLy3v0Aw9UvgLTzq','BxnNCZO','mZb2uhfHvfa','y29UDgvUDa','zNvSBa','sw5Qzwn0zwqGzMLSzsbHDhrHy2HTzw50ignVBNrLEhqGzM9YigfNzw50ia','y29TCgfJDgLVBL9LDMvUDa','sgfUzgXLihvZzxiGCMvXDwvZDdOGiG','zM9YBwf0vg9VBfjLC3vSDa','qwDLBNqG','yxv0B0nYzwf0zvrHC2TZrM9YtwvZC2fNzxm','qwXSignVBxbHy3rPB24Gyxr0zw1WDhmGzMfPBgvK','zgvWzw5Kzw5JAwvZ','u3rHCNrPBMCGqwDLBNqGu2nOzwr1BgvYihDPDgGGvc9nl1uGCxvLDwuGC3LZDgvT','y2fSy3vSyxrLq29UDgvUDfnPBwLSyxjPDhK','yxv0B0nYzwf0zuLUAxrPywXuyxnRswzozwvKzwq','z2v0t3DUuhjVCgvYDhLoyw1LCW','Bw9Kzq','C3vIC3rY','CMvJzwL2zwq','su5Fufjpr1jfu1m','zMLSDgvY','C2v0','mZaYnJG5mgLSDu9ACG','ota0BfneCgfO','Dg9gAxHLza','yMXVy2TLza','qxv0BY1JCMvHDgvKihrHC2SGzM9YihvZzxiGBwvZC2fNzq','qxv0BY1JCMvHDgvKigLUAxrPywWGDgfZAYbMB3iGywDLBNqG','BwvZC2fNzvf1zxvLCW','Dg9VBev4zwn1DgLVBNm','rMfPBgvKihrVigLUAxrPywXPEMuGzxHPC3rPBMCGywDLBNrZ','BwvZC2fNzxm','uMvZCg9Uzcb0BYa','quDftLq','z2v0vgLTzq','y29TCgfJDgLVBLbLCMzVCM1Lza','C2vSzwn0zwrnB2rLBa','ihn0yxrLigfSCMvHzhKGChjVy2vZC2vKlcbZA2LWCgLUzYbKDxbSAwnHDguGAxrLCMf0Aw9U','vg9VBcbLEgvJDxrPB24GzMfPBgvKoIa','z2v0u3rHDhvZ','ChjVy2vZC0fjuMvZCg9UC2u','Dhj1BMnHDgvdB250zw50','AgfZuhjVy2vZC2vKu3rHDgu','uhjVy2vZCYb1C2vYihjLCxvLC3q6ia','ChjPB3jPDhLty29Yzq','w0nptvbbq1qTu0Tjufbfrf0','q29TCgfJDgLVBIbJB21WBgv0zwqGzM9YigfNzw50ia','ywLtzxj2AwnL','BM93','igHHCYbUBYbZzxnZAw9UieLeic0GqvbjigTLEsbYzxnVBhv0Aw9UihDPBgWGzMfPBa','u2TPChbPBMCGAw5Hy3rPDMuGywDLBNq6ia','ksbMB3iGywDLBNqG','BgvUz3rO','q0HbvcbHz2vUDca','B3jPz2LUywXuB2TLBKnVDw50','DgfZAY1PBML0AwfSlq','BMfTzq','yxbPigTLEq','y29TCgXLDgvK','otG3m0XttKnfwa','ihbHDxnLzcbKDwuGDg8GqvbjigTLEsbPC3n1zq','yNvPBgreEw5HBwLJq29UDgv4Da','vvnfuG','BwvZC2fNzv9HzgrLza','y29TCgfJDgLVBLnLCNzPy2u','ywn0AxzLqwDLBNrZ','qxv0BY1JCMvHDgvKihrHC2SGzM9YigLUDgvYlwfNzw50ig1LC3nHz2u','w0nptvbbq1qTtuvuqurbvefD','qwDLBNqGiG','zgvZy3jPChrPB24','ChjVy2vZC0fNzw50qxv0B25VBw91C2X5','u2v0igfNzw50ign1CNjLBNrnB2rLBcb0BYa','y2HLy2TbBMrqzxjMB3jTq29TCgfJDgLVBG','Dg9Rzw5dB3vUDgLUz1nLCNzPy2u','iIbOywqGBM8Gy3vYCMvUDe1VzgvSihnLDc4Gqxv0B21HDgLJywXSEsbYzxn0B3jLzcb0BYa','y29UDgv4DeLUAMvJDgLVBLnLCNzPy2u','ywrKvg9VBfjLC3vSDa','qwDLBNqGBM90igzVDw5K','cGPjtvbpuLrbtLq6ifLVDsbHCMuGAw4GquDftLqGBw9Kzs4GvgHLihvZzsbVzIbuyxnRtwfUywDLCIb0B29SigLZig1HBMrHDg9YEs4GqwX3yxLZignYzwf0zsbHBMqGDxbKyxrLihrHC2TZihrVihrYywnRihLVDxiGD29YAYbWCM9NCMvZCY4GvxbKyxrLihrOzsb1C2vYigfIB3v0ihrHC2STBgLZDcbZDgf0DxmGCgvYAw9KAwnHBgX5lIbvC2uGDgHLigPVyMrVBMuGDg9VBcb3AgvUihLVDxiGBwfPBIb0yxnRigLZignVBxbSzxrLlG','CMvTB3zLqwDLBNq','Dg9tDhjPBMC','ihn0B3aGCMvXDwvZDgvKic0GCMvTB3zPBMCGzNjVBsbZy2HLzhvSzxi','z2v0tw9KzwXnyxHpDxrWDxruB2TLBNm','BMv0D29YAW','C3rVCefNzw50rxHLy3v0Aw9U','rhLUyw1PyYbYB3v0Aw5NoIbZD2L0y2HPBMCGzNjVBsa','DxbKyxrLzef0','ChjPB3jPDhK','qvbjigTLEsbHDxrOzw50AwnHDgLVBIbMywLSzwqUifbSzwfZzsbJAgvJAYb5B3vYiefqssbRzxKGy29UzMLNDxjHDgLVBIbPBIbtzxr0Aw5NCY4','ywrKtwvZC2fNzvrVq29UDMvYC2f0Aw9U','tuLox01fu1nbr0vtx0zpuL9dt01qqunusu9o','DgfZAYbJB21WBgv0zwq','D2fYBG','DhjPz2DLCMvKqNK','yxv0BY1JCMvHDgvK','igHHCYbUBYbUzxCGBwvZC2fNzxmGlsbYzw1VDMLUzYbMCM9TihnJAgvKDwXLCG','D2vIu29JA2v0twfUywDLCG','ywDLBNrFD2fYBMLUzW','zMfPBgvK','C3vIC3rYAw5N','igHHCYbUBYb2ywXPzcbJB252zxjZyxrPB24Gzgf0ys4Gq29TCgfJDgLVBIbZA2LWCgvKlG','DgLTzxn0yw1W','ywKTCMvZCg9UC2uT','AgfZ','z2v0uhjVDg90ExbLt2y','uKvuuLLFrevmqvLFtvm','Aw5JBhvKzxm','uhjVy2vZCYbTzxnZywDL','Dg9Rzw5vC2fNzq','yNjVywrJyxn0vg9tzxnZAw9U','C2L6zq','zM9YrwfJAa','ig1LC3nHz2vZigzYB20G','CxvLDwvuExbL','zgvSyxLfBMruAw1L','y29TCgfJDgLVBKLUuhjVz3jLC3m','y29UDMvYC2f0Aw9UCW','q29UC29SAwrHDgvKia','z2v0','BgfZDezLDgnOzwq','Dg9ju09tDhjPBMC','vfjjr0DfuIbdt01qqunusu9o','C2vZC2LVBKLK','CMvHC29UAw5N','y29UC29SAwrHDgvKlq','tM8GDMfSAwqGy29UDMvYC2f0Aw9UigzVDw5KigzVCIbJB21Wywn0Aw9U','vxnPBMCGzMLYC3qGyxzHAwXHyMXLignVBNzLCNnHDgLVBIbRzxKGzM9YignVBxbHy3rPB24Gy2HLy2S6ia','DgLTzw91Da','igLZihbHDxnLzcb1BNrPBca','DMfSAwq','mtGYmZGWq3vpwhrU','Aw5JB21PBMDnzxnZywDLCW','C3rHDhvZ','CM9Szq','CgvUzgLUzW','C3LZDgvTuhjVBxb0','u1Ltvevn','Dg9VBa','rMfPBgvKihrVihvWzgf0zsbKzxbLBMrLBNqGDgfZA3mGzM9YigfNzw50ia','CMvKDwn0Aw9UugvYy2vUDa','lcbWCM9JzwvKAw5NihDPDgGGquKGCMvXDwvZDa','AgfZugvUzgLUz1rHC2TZ','quKGCMvZCg9UC2uGzMfPBgvKigzVCIbHz2vUDca','Dg9VBfjLC3vSDhm','DgfZA3m','AgfZvw5WCM9JzxnZzwrnzxnZywDLCW','u1rbuLrjtKC','CgvYC2LZDefNzw50u3rHDgu','vw5RBM93BIbbz2vUDa','C3bSAxq','icSG','y2fSy3vSyxrLvgfYz2v0vg9Rzw5dB3vUDa','y29TCgfJDenVBNzLCNnHDgLVBG','nJG2mJi5EKDfwe16','y29TCgfJDgL6yxrPB25dB3vUDa','Bw9Kzvn0yxrL','lI4U','C3rYAw5NAwz5','z2vUzxjHDgvbz2vUDfn0yxrLsgfZAa','Aw5MBW','zxjYB3i','ChvZAa','Axnbz2vUDeLUu2nOzwr1BgvY','qwDLBNqGD2fZigfSCMvHzhKGAw4GquDftLqGBw9Kzq','y2XLyw51Ca','y2f0y2G','ChjVy2vZC2vKu3rHDgviyxnOzxm','C2vUze1LC3nHz2u','CMvWBgfJzq','AgfUzgXLquLtzxj2AwnLrMfPBhvYzq','C2nOzwr1BgvYlxbYB21WDa','Dg9VBeLK','ChjVy2vZC2LUz0LUuhjVz3jLC3m','DgfZA0XPC3q','BwfYA1n0yxrLqxnqCM9JzxnZzwq','zMLUza','q29TCgfJDgLVBIbHDhrLBxb0ia','z2v0tw9KzwXZ','B3jPz2LUywXnzxnZywDLCW','yNjVywrJyxn0q29TCgfJDgLVBKv2zw50','u0TjucaTigjLBg93ihrOCMvZAg9Sza','CMv2zxjZzq','qwDLBNqGBw9KzwWGy29UzMLNDxjHDgLVBIbYzxn0B3jLza','uhjVy2vZCYb1C2vYihjLCxvLC3q','BwfW','zxH0CMfJDfrHC2TuAxrSzq','y2XLyxi','Bw9KzwXZu2vYDMLJzq','vgfZAYb1BMjSB2nRzwqGzhvLihrVigrLCgvUzgvUy3KGy29TCgXLDgLVBG','quKGC2vYDMLJzsbLCNjVCJOG','A2v5CW','Bg9N','qwDLBNqGChjVy2vZC2LUzYbMywLSzwq6ia','C2HVDwXKqNjVywrJyxn0twvZC2fNzq','C29Tzq','zgvSzxrL','tufyx0LurvjbveLptLnFuevsx0nzq0Xf','rMfPBgvKihrVigf1Dg8TChjVz3jLC3mGDgfZAYbMB3iGywDLBNqG','nda3mZa5DMnlDLL5','sgfUzgXLig1LC3nHz2uGzNjVBsa','C2XPy2u','CMfUzg9T','igfKzgvKihrVihnJAgvKDwXLCIb3AxrOB3v0ihnLC3nPB25jzcaTiefqssbRzxKGCMvZB2X1DgLVBIbTyxKGzMfPBa','DgL0Bgu','C3rVChbLzc1IEs11C2vY','C2nOzwr1BgvYlxnLC3nPB24','C2vUzgvY','AxnsDw5UAw5N','y3vYCMvUDe1VzgvS','Bg9Nz2vY','qwDLBNqGBw9KzwWGy29UzMLNDxjHDgLVBIbPC3n1zsbKzxrLy3rLzcaTihvZAw5NigzHBgXIywnR','ChjLzMvYCMvKtw9KzwW','CMvHC29U','ywDLBNrFzxjYB3i','quDhuKvtu0Lwrq','zMLSDgvYqxzHAwXHyMXLvgfZA3m','tufyx1jfvfjzx0fuvevnufrt','ywrKqwDLBNq','y29TCgfJDgvKvg9Rzw5dB3vUDa','zNjVBq','qwDLBNqGu2nOzwr1BgvYihn0B3bWzwq','lcbHz2vUDc5JDxjYzw50tw9KzwW9','nLviDu9bAW','nJbrA0vSvMu','q0Hbva','tM8Gy29TCgfJDgLVBIb5zxqSihvZAw5Nig9YAwDPBMfS','Bw9KzwXsB3v0zxjtzxj2AwnL','DxnLCK1LC3nHz2vZ','u2nOzwr1BgvYihbYB2nLC3nPBMCGy3LJBguGzMfPBgvKoG','Dg9VBc1Yzxn1BhqT','DMfSAwrHDgvdB21Wywn0Aw9U','qwXSihbLBMrPBMCGDgfZA3mGyxjLigjSB2nRzwqGyNKGzgvWzw5Kzw5JAwvZigzVCIbHz2vUDca','lcbTB2rLBca','twvZC2fNzsbMCM9Tia','revgqvvmvf9usfjfu0Hpteq','uhjVy2vZCYbPBML0AwfSihjLCxvLC3q6ia','C2nOzwr1BgvjBNrLCNzHBa','BwvZC2fNzvbYB2nLC3nVCG','CMvZDwX0','C3rHy2S','igHHCYbUBYbWzw5KAw5NihrHC2TZig9Yig1LC3nHz2vZic0GCMvTB3zPBMCGzNjVBsbZy2HLzhvSzxi','Aw50zxjbz2vUDe1LC3nHz2vZ','z2v0qwDLBNq','BgfZDfr5Cgu','ywDLBNrqB29S','DgfZAY0','DgfZA0LK','C3LZDgvTlwvYCM9Y','BwvZC2fNzq','Cgf1C2vKvw50AwW','ngTRs0HNyG','C3rHCNq','rMfPBgvKihrVihn0B3aGywDLBNqGzxHLy3v0Aw9UoIa','zgvIDwC','qundvvjbveu','DhLWzq','yxv0AgvUDgLJyxrPB24','Aw5FChjVz3jLC3m','AM9PBG','Aw50zxjbz2vUDfrYywnRAw5N','ywDLBNrqCM9JzxnZAw5Ntg9JA3m','AgfZvg9VBev4zwn1DgLVBNm','Aw5PDgLHBgL6zuv4Axn0Aw5NqwDLBNrZ','ChjVy2vZC0fNzw50','ywrK','zxHLy3v0Aw9Ux3n0B3bWzwq','AxndB21Wywn0zwq','igHHCYbKDxbSAwnHDguGC3rHDguGD2L0AcbUBYbUzxCGBwvZC2fNzxmGlsbYzw1VDMLUzYbMCM9TihnJAgvKDwXLCG','y29TCgfJDgvKtwvZC2fNzxm','rhLUyw1PyYbYB3v0Aw5NigzHAwXLzcWGDxnPBMCGy3vYCMvUDcbTB2rLBdOG','BgfZDfjLy2vPDMvK','z2v0qwXSqwDLBNrZ','DhjPBq','DxnLCG','ihbHDxnLzcbKDwuGDg8GDw5RBM93BIbbssbZzxj2AwnLigvYCM9YoIa','rMfPBgvKihrVigLUAMvJDcbMAwXLigf0DgfJAg1LBNqGy29UDgv4DcbMB3iGywDLBNqG','iokgKIa'];a0_0xfca2=function(){return _0x3dd9c0;};return a0_0xfca2();}class AgentScheduler{constructor(_0x971094,_0x2b24db,_0x3c8654,_0x526966,_0x31d83b=null,_0x314a1c=null,_0x4a0107=null){const _0x4c5afc=a0_0x2d8a;this['agentPool']=_0x971094,this[_0x4c5afc(0x124)]=_0x2b24db,this['aiService']=_0x3c8654,this['logger']=_0x526966,this['webSocketManager']=_0x31d83b,this[_0x4c5afc(0x119)]=_0x314a1c,this[_0x4c5afc(0xf2)]=_0x4a0107,this['contextInjectionService']=new a0_0x59e710({},_0x526966),this[_0x4c5afc(0x1a0)]=new a0_0x2b4723(_0x526966),this[_0x4c5afc(0x197)]=new a0_0x491e7f(this[_0x4c5afc(0x1a0)],_0x3c8654,_0x526966),this['compactionInProgress']=new Map(),this[_0x4c5afc(0x106)]=![],this['activeAgents']=new Map(),this['scheduleInterval']=null,this['processedStateHashes']=new Map(),this[_0x4c5afc(0xe3)]=![],this['agentProcessingLocks']=new Map(),this['ITERATION_DELAY']=0x3e8,this[_0x4c5afc(0xfb)]=0x186a0;}[a0_0x567dbc(0x132)](){const _0x4fba2c=a0_0x567dbc;if(this['isRunning']){this[_0x4fba2c(0x108)]['info']('Agent\x20scheduler\x20is\x20already\x20running');return;}this['isRunning']=!![],this['logger'][_0x4fba2c(0xd6)](_0x4fba2c(0x163)),this[_0x4fba2c(0x13d)](),this[_0x4fba2c(0x123)]=setInterval(()=>{const _0x813a4=_0x4fba2c;this['processingCycle']()[_0x813a4(0xdc)](_0x5bfc7c=>{const _0x5680db=_0x813a4;this['logger']['error'](_0x5680db(0x11b),_0x5bfc7c);});},this['ITERATION_DELAY']);}async['initializeExistingAgents'](){const _0x4ab9c8=a0_0x567dbc;try{const _0x251833=await this[_0x4ab9c8(0x12b)][_0x4ab9c8(0x146)]();let _0x4f5f70=0x0;for(const _0x25f35e of _0x251833){if(_0x25f35e[_0x4ab9c8(0x167)]===AGENT_MODES[_0x4ab9c8(0x178)]){this['logger']['info']('Initializing\x20existing\x20AGENT\x20mode\x20agent:\x20'+_0x25f35e['id'],{'agentName':_0x25f35e['name'],'sessionId':_0x25f35e['sessionId']});const _0x5e7a84=this['activeAgents'][_0x4ab9c8(0x1cd)](_0x25f35e['id']),_0x49e79d=_0x5e7a84?.[_0x4ab9c8(0x1d1)]||_0x25f35e['sessionId'];await this['addAgent'](_0x25f35e['id'],{'sessionId':_0x49e79d,'triggeredBy':'scheduler-startup','reason':_0x4ab9c8(0xda)}),_0x4f5f70++;}}this['logger'][_0x4ab9c8(0xd6)]('Initialized\x20'+_0x4f5f70+'\x20existing\x20AGENT\x20mode\x20agents\x20into\x20scheduler');}catch(_0x109657){this[_0x4ab9c8(0x108)][_0x4ab9c8(0xd7)](_0x4ab9c8(0x175),{'error':_0x109657[_0x4ab9c8(0x12f)]});}}['stop'](){const _0x3ca538=a0_0x567dbc;if(!this[_0x3ca538(0x106)])return;this['isRunning']=![],this['scheduleInterval']&&(clearInterval(this['scheduleInterval']),this['scheduleInterval']=null),this[_0x3ca538(0x198)][_0x3ca538(0xf1)](),this['compactionInProgress'][_0x3ca538(0xf1)](),this['tokenCountingService']&&this['tokenCountingService'][_0x3ca538(0xdb)]&&this[_0x3ca538(0x1a0)]['cleanup'](),this[_0x3ca538(0x108)][_0x3ca538(0xd6)](_0x3ca538(0x113));}async[a0_0x567dbc(0x110)](_0x28035a,_0x168a48={}){const _0xc0fe02=a0_0x567dbc,_0x267d8d=await this['agentPool']['getAgent'](_0x28035a);if(!_0x267d8d){this[_0xc0fe02(0x108)][_0xc0fe02(0x1b3)]('Cannot\x20add\x20agent\x20to\x20scheduler\x20-\x20agent\x20not\x20found:\x20'+_0x28035a);return;}if(_0x267d8d[_0xc0fe02(0x1db)]!=='active'){this[_0xc0fe02(0x108)][_0xc0fe02(0x134)](_0xc0fe02(0x189)+_0x28035a+'\x20(status:\x20'+_0x267d8d[_0xc0fe02(0x1db)]+')');return;}!_0x168a48[_0xc0fe02(0x1d1)]&&this[_0xc0fe02(0x108)]['warn'](_0xc0fe02(0x15f)+_0x28035a+_0xc0fe02(0x101),{'agentName':_0x267d8d['name'],'triggeredBy':_0x168a48['triggeredBy']}),this[_0xc0fe02(0x198)]['set'](_0x28035a,{'sessionId':_0x168a48[_0xc0fe02(0x1d1)],'triggeredBy':_0x168a48['triggeredBy']||'unknown','addedAt':new Date()[_0xc0fe02(0x1cf)]()}),!this[_0xc0fe02(0xdd)]['has'](_0x28035a)&&this[_0xc0fe02(0xdd)]['set'](_0x28035a,new Set()),this[_0xc0fe02(0x108)][_0xc0fe02(0xd6)]('Agent\x20added\x20to\x20scheduler:\x20'+_0x28035a,{'agentMode':_0x267d8d[_0xc0fe02(0x167)],'activeAgents':this['activeAgents'][_0xc0fe02(0x1c5)],'sessionId':_0x168a48['sessionId']||'NO_SESSION_ID','contextKeys':Object[_0xc0fe02(0xf5)](_0x168a48),'triggeredBy':_0x168a48[_0xc0fe02(0x1b4)]||'unknown'}),!this['isRunning']&&this['start']();}[a0_0x567dbc(0x1a6)](_0x1990b6,_0x194cc1='completed'){const _0x21692e=a0_0x567dbc;this['activeAgents'][_0x21692e(0x1be)](_0x1990b6)&&(this[_0x21692e(0x198)][_0x21692e(0xfa)](_0x1990b6),this[_0x21692e(0xdd)]['delete'](_0x1990b6),this['logger'][_0x21692e(0xd6)]('Agent\x20removed\x20from\x20scheduler:\x20'+_0x1990b6,{'reason':_0x194cc1,'remainingAgents':this['activeAgents'][_0x21692e(0x1c5)]}),this[_0x21692e(0x198)][_0x21692e(0x1c5)]===0x0&&this['stop']());}[a0_0x567dbc(0xd9)](_0x1b4c51){const _0x520892=a0_0x567dbc;return this[_0x520892(0x198)]['has'](_0x1b4c51);}async[a0_0x567dbc(0x1ab)](_0x89b783){const _0x569f7d=a0_0x567dbc;try{const _0x174a10=await this['agentPool']['getAgent'](_0x89b783);if(!_0x174a10)return{'success':![],'error':'Agent\x20not\x20found'};_0x174a10[_0x569f7d(0x167)]=AGENT_MODES['CHAT'],_0x174a10[_0x569f7d(0xd2)]=AGENT_MODE_STATES['IDLE'],_0x174a10['delayEndTime']=null,await this['agentPool'][_0x569f7d(0xca)](_0x89b783),this['removeAgent'](_0x89b783,_0x569f7d(0x103));const _0x311738=this[_0x569f7d(0x198)]['get'](_0x89b783),_0x5da354=_0x311738?.['sessionId']||_0x174a10['sessionId'];return!_0x5da354&&this['logger']['warn']('Agent\x20'+_0x89b783+'\x20stopped\x20but\x20has\x20no\x20session\x20ID\x20for\x20broadcast',{'agentName':_0x174a10['name']}),_0x5da354&&this['webSocketManager']&&this[_0x569f7d(0x1b7)][_0x569f7d(0x1c4)]&&this['webSocketManager']['broadcastToSession'](_0x5da354,{'type':'execution_stopped','data':{'agentId':_0x89b783,'type':_0x569f7d(0x140),'modeState':'stopped','timestamp':new Date()[_0x569f7d(0x1cf)]()}}),this[_0x569f7d(0x108)]['info']('Agent\x20execution\x20stopped:\x20'+_0x89b783,{'mode':_0x174a10[_0x569f7d(0x167)],'modeState':_0x174a10[_0x569f7d(0xd2)]}),{'success':!![],'agent':{'id':_0x174a10['id'],'name':_0x174a10['name'],'mode':_0x174a10['mode'],'modeState':_0x174a10['modeState']}};}catch(_0x5c83b8){return this[_0x569f7d(0x108)][_0x569f7d(0xd7)](_0x569f7d(0x133)+_0x89b783,{'error':_0x5c83b8[_0x569f7d(0x12f)]}),{'success':![],'error':_0x5c83b8['message']};}}async['processingCycle'](){const _0x5dc59a=a0_0x567dbc;if(this['processingInProgress']){this[_0x5dc59a(0x108)][_0x5dc59a(0x134)]('Processing\x20cycle\x20already\x20in\x20progress,\x20skipping');return;}if(this['activeAgents'][_0x5dc59a(0x1c5)]===0x0)return;this['processingInProgress']=!![];try{const _0xaf1969=Array[_0x5dc59a(0x112)](this[_0x5dc59a(0x198)][_0x5dc59a(0xf5)]());for(const _0x17644e of _0xaf1969){try{if(!this[_0x5dc59a(0x198)]['has'](_0x17644e))continue;const _0x16ad52=await this[_0x5dc59a(0x13e)](_0x17644e);!_0x16ad52&&this[_0x5dc59a(0x1a6)](_0x17644e,'completed');}catch(_0x1ccaac){this['logger'][_0x5dc59a(0xd7)](_0x5dc59a(0xf7)+_0x17644e,{'error':_0x1ccaac[_0x5dc59a(0x12f)],'stack':_0x1ccaac[_0x5dc59a(0x126)]}),this[_0x5dc59a(0x1a6)](_0x17644e,'error');}}}finally{this[_0x5dc59a(0xe3)]=![];}}async[a0_0x567dbc(0x13e)](_0x5d38c1){const _0x49a84d=a0_0x567dbc;if(this[_0x49a84d(0x13b)]['get'](_0x5d38c1))return this['logger'][_0x49a84d(0x134)](_0x49a84d(0x15f)+_0x5d38c1+'\x20is\x20already\x20being\x20processed,\x20skipping'),!![];const _0x385164=await this['agentPool'][_0x49a84d(0x129)](_0x5d38c1);if(!_0x385164)return![];this[_0x49a84d(0x13b)][_0x49a84d(0x16c)](_0x5d38c1,!![]);try{if(_0x385164['delayEndTime']&&new Date()<new Date(_0x385164['delayEndTime']))return this['logger']['debug']('Agent\x20'+_0x5d38c1+'\x20is\x20delayed\x20until\x20'+_0x385164['delayEndTime']),!![];if(_0x385164[_0x49a84d(0x1db)]===_0x49a84d(0x14f)||_0x385164['pausedUntil']){if(_0x385164[_0x49a84d(0x130)]&&new Date()<new Date(_0x385164['pausedUntil']))return this[_0x49a84d(0x108)][_0x49a84d(0x134)](_0x49a84d(0x15f)+_0x5d38c1+_0x49a84d(0x1d7)+_0x385164[_0x49a84d(0x130)]),!![];}if(_0x385164['stopRequested'])return this[_0x49a84d(0x108)][_0x49a84d(0xd6)](_0x49a84d(0x15f)+_0x5d38c1+_0x49a84d(0x1a8)),![];const _0x279888=this[_0x49a84d(0xd5)](_0x385164);if(this[_0x49a84d(0x181)](_0x5d38c1,_0x279888)){this['logger']['debug']('Agent\x20'+_0x5d38c1+_0x49a84d(0x17c),{'stateHash':_0x279888,'agentMode':_0x385164['mode']});if(_0x385164['mode']===AGENT_MODES['CHAT']){const _0x51d912=_0x385164[_0x49a84d(0x173)][_0x49a84d(0x11a)][_0x49a84d(0x18b)]>0x0||_0x385164['messageQueues']['interAgentMessages'][_0x49a84d(0x18b)]>0x0;if(!_0x51d912)return this[_0x49a84d(0x108)][_0x49a84d(0x134)](_0x49a84d(0x18c)+_0x5d38c1+_0x49a84d(0x142)),![];}return!![];}const _0x33f6fe=_0x385164['messageQueues'];_0x33f6fe['userMessages'][_0x49a84d(0x18b)]>0x0&&this['logger']['info']('User\x20message\x20detected\x20for\x20agent\x20'+_0x5d38c1+'\x20-\x20will\x20be\x20prioritized',{'userMessageCount':_0x33f6fe['userMessages'][_0x49a84d(0x18b)],'agentMode':_0x385164['mode']});const _0x416d93=_0x33f6fe['toolResults']['length']+_0x33f6fe[_0x49a84d(0x128)]['length']+_0x33f6fe[_0x49a84d(0x11a)]['length'];if(_0x416d93===0x0&&_0x385164[_0x49a84d(0x167)]===AGENT_MODES[_0x49a84d(0x117)])return this[_0x49a84d(0x108)]['debug'](_0x49a84d(0x18c)+_0x5d38c1+'\x20has\x20no\x20queued\x20messages\x20-\x20removing\x20from\x20scheduler'),![];if(_0x416d93===0x0&&_0x385164[_0x49a84d(0x167)]===AGENT_MODES[_0x49a84d(0x178)]){await this['autoCreateInitialTaskIfNeeded'](_0x5d38c1);const _0x5a85bf=this[_0x49a84d(0x1e4)](_0x385164),hasUnprocessedMessages=this['hasUnprocessedMessages'](_0x385164);if(!_0x5a85bf&&!hasUnprocessedMessages)return this[_0x49a84d(0x108)][_0x49a84d(0xd6)]('AGENT\x20mode\x20agent\x20'+_0x5d38c1+_0x49a84d(0x127),{'agentName':_0x385164[_0x49a84d(0x18f)],'taskCount':_0x385164['taskList']?.[_0x49a84d(0x1e7)]?.[_0x49a84d(0x18b)]||0x0,'completedTasks':_0x385164['taskList']?.[_0x49a84d(0x1e7)]?.['filter'](_0x206bc0=>_0x206bc0['status']===_0x49a84d(0x191))[_0x49a84d(0x18b)]||0x0}),![];return await this['processAgentAutonomously'](_0x5d38c1);}const processedMessages=await this['processAgentQueues'](_0x5d38c1);if(processedMessages===0x0)return _0x385164['mode']===AGENT_MODES['CHAT']?![]:await this[_0x49a84d(0x19d)](_0x5d38c1);const _0x880d5e=await this['getAgentAIResponse'](_0x5d38c1);if(!_0x880d5e)return this[_0x49a84d(0x108)][_0x49a84d(0x1b3)]('No\x20AI\x20response\x20for\x20agent\x20'+_0x5d38c1),_0x385164[_0x49a84d(0x167)]===AGENT_MODES[_0x49a84d(0x178)];return await this[_0x49a84d(0x17f)](_0x5d38c1,_0x880d5e),this[_0x49a84d(0xe5)](_0x5d38c1,_0x279888),this['shouldAgentContinue'](_0x5d38c1,_0x385164);}finally{this[_0x49a84d(0x13b)][_0x49a84d(0xfa)](_0x5d38c1);}}async['processAgentQueues'](_0x44e252){const _0x6df392=a0_0x567dbc,_0x1eaa7e=await this['agentPool'][_0x6df392(0x129)](_0x44e252);if(!_0x1eaa7e)return 0x0;const _0x51ce10=_0x1eaa7e[_0x6df392(0x173)],_0x1ea420=[..._0x51ce10['toolResults'][_0x6df392(0xef)](_0x30b295=>({..._0x30b295,'queueType':'toolResults'})),..._0x51ce10['interAgentMessages'][_0x6df392(0xef)](_0x30f263=>({..._0x30f263,'queueType':'interAgentMessages'})),..._0x51ce10[_0x6df392(0x11a)]['map'](_0x571621=>({..._0x571621,'queueType':'userMessages'}))];if(_0x1ea420[_0x6df392(0x18b)]===0x0)return 0x0;_0x1ea420['sort']((_0x4e2763,_0xd0d7d0)=>new Date(_0x4e2763['timestamp']||_0x4e2763[_0x6df392(0x155)]||0x0)-new Date(_0xd0d7d0[_0x6df392(0x1bc)]||_0xd0d7d0['queuedAt']||0x0));let _0xa40a82='';const _0x309bb1=_0x1ea420['some'](_0x5df8d7=>_0x5df8d7[_0x6df392(0x1c8)]==='userMessages'),_0x3c3e9c=_0x1ea420['some'](_0x594440=>_0x594440['queueType']==='interAgentMessages'),_0x33e63e=_0x1ea420[_0x6df392(0xf9)](_0x1c78ba=>_0x1c78ba['queueType']==='toolResults'),_0x39fb5f=_0x1ea420[_0x6df392(0x16b)](_0x21714f=>_0x21714f[_0x6df392(0x1c8)]==='userMessages');_0x39fb5f[_0x6df392(0x18b)]>0x0&&_0x39fb5f[_0x6df392(0x1c6)](_0x3bdada=>{if(_0xa40a82)_0xa40a82+='\x0a\x0a';_0xa40a82+=_0x3bdada['content'];});const _0x1567fc=_0x1ea420['filter'](_0x18ffb9=>_0x18ffb9[_0x6df392(0x1c8)]===_0x6df392(0x128));if(_0x1567fc['length']>0x0){if(_0xa40a82)_0xa40a82+='\x0a\x0a';_0xa40a82+='[Agent\x20Messages]\x0a',_0x1567fc[_0x6df392(0x1c6)](_0x556f94=>{const _0x24df46=_0x6df392,_0x30d4f3=_0x556f94['senderName']||_0x556f94['sender']||_0x24df46(0xcb);_0xa40a82+=_0x30d4f3+':\x20'+_0x556f94['content']+'\x0a';});}const _0x2e73b7=_0x1ea420[_0x6df392(0x16b)](_0x18594e=>_0x18594e[_0x6df392(0x1c8)]==='toolResults');if(_0x2e73b7[_0x6df392(0x18b)]>0x0){if(_0xa40a82)_0xa40a82+='\x0a\x0a';_0xa40a82+='[Previous\x20Tool\x20Results]\x0a',_0x2e73b7[_0x6df392(0x1c6)](_0x42fcf3=>{const _0x1c4389=_0x6df392;_0xa40a82+=this[_0x1c4389(0x15e)](_0x42fcf3)+'\x0a';});}_0x3c3e9c&&(_0xa40a82+='\x0aNote:\x20Use\x20the\x20agentcommunication\x20tool\x20if\x20you\x20need\x20to\x20respond\x20to\x20other\x20agents.');await this[_0x6df392(0x160)](_0x44e252,_0x39fb5f,_0x1567fc);const _0x24527c={'id':_0x6df392(0x1d3)+Date[_0x6df392(0x187)](),'role':MESSAGE_ROLES[_0x6df392(0x195)],'content':_0xa40a82['trim'](),'timestamp':new Date()['toISOString'](),'type':'consolidated-input','originalMessageCount':_0x1ea420[_0x6df392(0x18b)]};await this[_0x6df392(0x1b0)](_0x44e252,_0x24527c,![]);if(_0x1eaa7e&&_0x1567fc['length']>0x0){for(const _0x25a4ec of _0x1567fc){if(_0x25a4ec['sender']){!_0x1eaa7e[_0x6df392(0x13a)][_0x6df392(0x1be)](_0x25a4ec['sender'])&&_0x1eaa7e[_0x6df392(0x13a)]['set'](_0x25a4ec['sender'],{'lastSent':null,'lastReceived':null,'lastType':null});const _0x14e9f0=_0x1eaa7e['interAgentTracking']['get'](_0x25a4ec['sender']);_0x14e9f0['lastReceived']=Date[_0x6df392(0x187)](),_0x14e9f0[_0x6df392(0x12a)]=_0x6df392(0x169);}}await this['agentPool']['persistAgentState'](_0x44e252);}return _0x51ce10['toolResults'][_0x6df392(0x18b)]=0x0,_0x51ce10[_0x6df392(0x128)]['length']=0x0,_0x51ce10['userMessages'][_0x6df392(0x18b)]=0x0,await this[_0x6df392(0x12b)]['persistAgentState'](_0x44e252),this['logger']['debug'](_0x6df392(0x1cc)+_0x1ea420[_0x6df392(0x18b)]+'\x20queued\x20messages\x20for\x20agent\x20'+_0x44e252),_0x1ea420[_0x6df392(0x18b)];}async['addMessageToConversation'](_0x356aa8,_0x56e20f,_0x34b51b=!![]){const _0x544c47=a0_0x567dbc,_0x1c7187=await this[_0x544c47(0x12b)][_0x544c47(0x129)](_0x356aa8);if(!_0x1c7187)return;let _0x56409b;switch(_0x56e20f[_0x544c47(0x1c8)]){case'toolResults':_0x56409b={..._0x56e20f,'role':_0x544c47(0x1e0),'content':this[_0x544c47(0x15e)](_0x56e20f)};break;case'interAgentMessages':_0x56409b={..._0x56e20f,'role':MESSAGE_ROLES[_0x544c47(0x1df)],'content':_0x544c47(0x120)+(_0x56e20f['senderName']||_0x56e20f['sender'])+':\x20'+_0x56e20f['content']};break;case _0x544c47(0x11a):_0x56409b={..._0x56e20f,'role':MESSAGE_ROLES[_0x544c47(0x195)]};break;default:_0x56409b=_0x56e20f;}!_0x56409b['timestamp']&&(_0x56409b[_0x544c47(0x1bc)]=new Date()[_0x544c47(0x1cf)]()),_0x1c7187['conversations']['full'][_0x544c47(0x176)][_0x544c47(0xd8)](_0x56409b),_0x1c7187[_0x544c47(0x1cb)][_0x544c47(0x15a)]['lastUpdated']=new Date()[_0x544c47(0x1cf)](),_0x1c7187[_0x544c47(0x107)]&&_0x1c7187[_0x544c47(0x1cb)][_0x1c7187['currentModel']]&&(_0x1c7187['conversations'][_0x1c7187[_0x544c47(0x107)]][_0x544c47(0x176)]['push'](_0x56409b),_0x1c7187[_0x544c47(0x1cb)][_0x1c7187['currentModel']][_0x544c47(0x153)]=new Date()[_0x544c47(0x1cf)]()),_0x34b51b&&this['shouldBroadcastMessage'](_0x56409b)&&this['broadcastMessageUpdate'](_0x356aa8,_0x56409b);}async['processAgentAutonomously'](_0x1f3ea1){const _0x3bcdb7=a0_0x567dbc;await this['autoProgressHighestPriorityTask'](_0x1f3ea1);const _0x38a17e=await this['getAgentAIResponse'](_0x1f3ea1);if(!_0x38a17e)return!![];await this[_0x3bcdb7(0x17f)](_0x1f3ea1,_0x38a17e);const _0x4be6f0=await this[_0x3bcdb7(0x12b)]['getAgent'](_0x1f3ea1);return this['shouldAgentContinue'](_0x1f3ea1,_0x4be6f0);}async['checkAndPerformCompaction'](_0x33495b,_0x3465fe,_0x3796b4){const _0x54e14c=a0_0x567dbc,_0x101bfa=process['env']['COMPACT_DEBUG']===_0x54e14c(0x14c);_0x101bfa&&console['log']('[COMPACT-CHECK-START]',{'agentId':_0x33495b,'targetModel':_0x3465fe,'sessionId':_0x3796b4,'timestamp':new Date()[_0x54e14c(0x1cf)]()});try{const _0x16c9cd=await this['agentPool']['getAgent'](_0x33495b);if(!_0x16c9cd)return _0x101bfa&&console[_0x54e14c(0xf6)]('[COMPACT-ERROR]',{'agentId':_0x33495b,'reason':_0x54e14c(0x1a4)}),{'shouldContinue':![],'error':_0x54e14c(0x1a4)};let _0x46f048=_0x16c9cd[_0x54e14c(0x107)]&&_0x16c9cd[_0x54e14c(0x107)]!==_0x3465fe?_0x16c9cd['currentModel']:_0x3465fe;if(!_0x46f048){this['logger'][_0x54e14c(0x1b3)](_0x54e14c(0x15f)+_0x33495b+'\x20has\x20no\x20currentModel\x20or\x20targetModel\x20set,\x20attempting\x20to\x20use\x20available\x20conversation',{'agentId':_0x33495b,'currentModel':_0x16c9cd['currentModel'],'targetModel':_0x3465fe,'preferredModel':_0x16c9cd[_0x54e14c(0x10a)],'availableConversations':Object[_0x54e14c(0xf5)](_0x16c9cd['conversations']||{})}),this['broadcastCompactionEvent'](_0x33495b,_0x3796b4,{'status':'warning','message':_0x54e14c(0x109),'details':'Agent\x20has\x20no\x20currentModel\x20set.\x20Using\x20fallback\x20model\x20for\x20compaction\x20check.','agentName':_0x16c9cd['name']});if(_0x16c9cd['preferredModel']&&_0x16c9cd[_0x54e14c(0x1cb)][_0x16c9cd['preferredModel']])_0x46f048=_0x16c9cd['preferredModel'],this['logger']['info']('Using\x20preferredModel\x20as\x20fallback\x20for\x20compaction\x20check:\x20'+_0x46f048);else{const _0x59015=Object[_0x54e14c(0xf5)](_0x16c9cd['conversations']||{})['filter'](_0x41fc3a=>_0x41fc3a!==_0x54e14c(0x15a));if(_0x59015[_0x54e14c(0x18b)]>0x0)_0x46f048=_0x59015[0x0],this[_0x54e14c(0x108)]['warn'](_0x54e14c(0x1d5)+_0x46f048);else return this[_0x54e14c(0x108)]['error']('No\x20valid\x20conversation\x20found\x20for\x20agent\x20'+_0x33495b+',\x20skipping\x20compaction'),this[_0x54e14c(0xea)](_0x33495b,_0x3796b4,{'status':'error','message':_0x54e14c(0x1d4),'details':_0x54e14c(0x15f)+_0x16c9cd[_0x54e14c(0x18f)]+_0x54e14c(0x1bb),'agentName':_0x16c9cd[_0x54e14c(0x18f)]}),{'shouldContinue':!![],'error':'No\x20valid\x20conversation\x20found'};}}const _0x14f43c=await this[_0x54e14c(0x12b)]['getCompactionMetadata'](_0x33495b,_0x46f048);_0x101bfa&&console[_0x54e14c(0xf6)](_0x54e14c(0x19a),{'agentId':_0x33495b,'modelToCheck':_0x46f048,'hasMetadata':!!_0x14f43c,'isCompacted':_0x14f43c?.[_0x54e14c(0x141)],'originalMessageCount':_0x14f43c?.[_0x54e14c(0xe9)]?.['length']||0x0,'compactedMessageCount':_0x14f43c?.[_0x54e14c(0x143)]?.[_0x54e14c(0x18b)]||0x0,'lastCompactization':_0x14f43c?.['lastCompactization']||'never','compactizationCount':_0x14f43c?.[_0x54e14c(0xd1)]||0x0,'originalTokenCount':_0x14f43c?.[_0x54e14c(0x18d)]||0x0,'compactedTokenCount':_0x14f43c?.['compactedTokenCount']||0x0});if(!_0x14f43c||!_0x14f43c['originalMessages']&&!_0x14f43c[_0x54e14c(0x143)])return this[_0x54e14c(0x108)]['debug']('Compaction\x20skipped:\x20no\x20conversation\x20metadata\x20for\x20agent\x20'+_0x33495b+_0x54e14c(0x11f)+_0x46f048),_0x101bfa&&console['log'](_0x54e14c(0x184),{'agentId':_0x33495b,'reason':'No\x20conversation\x20metadata'}),{'shouldContinue':!![]};const _0x404d0b=_0x14f43c[_0x54e14c(0x141)]?_0x14f43c[_0x54e14c(0x143)]:_0x14f43c['originalMessages'];_0x101bfa&&console[_0x54e14c(0xf6)](_0x54e14c(0x14e),{'agentId':_0x33495b,'selectedArray':_0x14f43c[_0x54e14c(0x141)]?_0x54e14c(0x143):'originalMessages','messageCount':_0x404d0b?.[_0x54e14c(0x18b)]||0x0,'reason':_0x14f43c['isCompacted']?'Compaction\x20exists,\x20using\x20compacted\x20version':_0x54e14c(0x118)});if(!_0x404d0b||_0x404d0b[_0x54e14c(0x18b)]<COMPACTION_CONFIG[_0x54e14c(0x1b1)])return this['logger'][_0x54e14c(0x134)]('Compaction\x20skipped:\x20too\x20few\x20messages\x20('+(_0x404d0b?.['length']||0x0)+_0x54e14c(0x18a)+_0x33495b),_0x101bfa&&console['log']('[COMPACT-SKIPPED]',{'agentId':_0x33495b,'reason':'Too\x20few\x20messages','messageCount':_0x404d0b?.[_0x54e14c(0x18b)]||0x0,'minRequired':COMPACTION_CONFIG[_0x54e14c(0x1b1)]}),{'shouldContinue':!![]};const _0x4235a0=await this[_0x54e14c(0x1a0)]['estimateConversationTokens'](_0x404d0b,_0x3465fe,TOKEN_COUNTING_MODES[_0x54e14c(0x135)]),_0x38f5a1=this[_0x54e14c(0x1a0)]['getModelContextWindow'](_0x3465fe),_0x109cf0=this['tokenCountingService'][_0x54e14c(0x1a9)](_0x3465fe);_0x101bfa&&console['log']('[COMPACT-TOKEN-COUNT]',{'agentId':_0x33495b,'currentTokens':_0x4235a0,'maxOutputTokens':_0x109cf0,'contextWindow':_0x38f5a1,'model':_0x3465fe,'countingMode':'ACCURATE'});const _0x4dc611=_0x16c9cd['compactionThreshold']||COMPACTION_CONFIG[_0x54e14c(0x121)],_0xddf415=this[_0x54e14c(0x1a0)]['shouldTriggerCompaction'](_0x4235a0,_0x109cf0,_0x38f5a1,_0x4dc611);if(_0x101bfa){const requiredTokens=_0x4235a0+_0x109cf0,_0x3bb3f1=_0x4dc611*_0x38f5a1;console['log']('[COMPACT-TRIGGER-CHECK]',{'agentId':_0x33495b,'currentTokens':_0x4235a0,'maxOutputTokens':_0x109cf0,'requiredTokens':requiredTokens,'contextWindow':_0x38f5a1,'threshold':_0x4dc611,'thresholdTokens':_0x3bb3f1,'shouldCompact':_0xddf415,'formula':_0x4235a0+_0x54e14c(0xcd)+_0x109cf0+'\x20=\x20'+requiredTokens+'\x20'+(_0xddf415?'>=':'<')+'\x20'+_0x3bb3f1+'\x20('+_0x4dc611*0x64+'%\x20of\x20'+_0x38f5a1+')','decision':_0xddf415?_0x54e14c(0x1d0):_0x54e14c(0xeb)});}if(!_0xddf415)return _0x101bfa&&console['log'](_0x54e14c(0x184),{'agentId':_0x33495b,'reason':'Below\x20threshold','utilizationPct':((_0x4235a0+_0x109cf0)/_0x38f5a1*0x64)[_0x54e14c(0x16f)](0x1)}),{'shouldContinue':!![]};this['logger'][_0x54e14c(0xd6)]('Compaction\x20triggered\x20for\x20agent\x20'+_0x33495b,{'currentTokens':_0x4235a0,'contextWindow':_0x38f5a1,'threshold':(_0x4dc611*0x64)['toFixed'](0x0)+'%','utilization':((_0x4235a0+_0x109cf0)/_0x38f5a1*0x64)['toFixed'](0x1)+'%','targetModel':_0x3465fe});_0x101bfa&&console[_0x54e14c(0xf6)]('[COMPACT-TRIGGERED]',{'agentId':_0x33495b,'reason':'Threshold\x20exceeded','currentTokens':_0x4235a0,'maxOutputTokens':_0x109cf0,'requiredTokens':_0x4235a0+_0x109cf0,'contextWindow':_0x38f5a1,'threshold':_0x4dc611,'utilizationPct':((_0x4235a0+_0x109cf0)/_0x38f5a1*0x64)[_0x54e14c(0x16f)](0x1)});this[_0x54e14c(0x1ca)][_0x54e14c(0x16c)](_0x33495b,COMPACTION_STATUS['STARTING']),this['broadcastCompactionEvent'](_0x33495b,_0x3796b4,{'status':COMPACTION_STATUS[_0x54e14c(0xc9)],'currentTokens':_0x4235a0,'targetTokens':this['tokenCountingService'][_0x54e14c(0xce)](_0x38f5a1),'contextWindow':_0x38f5a1,'model':_0x3465fe});let _0x5e8b67=COMPACTION_STRATEGIES['SUMMARIZATION'];const _0x1b4ebc=_0x16c9cd['currentModel'];_0x1b4ebc&&_0x1b4ebc!==_0x3465fe&&(_0x5e8b67=COMPACTION_STRATEGIES['TRUNCATION'],this[_0x54e14c(0x108)]['info']('Using\x20truncation\x20strategy\x20for\x20model\x20switch:\x20'+_0x1b4ebc+_0x54e14c(0x14b)+_0x3465fe));this[_0x54e14c(0x1ca)]['set'](_0x33495b,COMPACTION_STATUS[_0x54e14c(0x16a)]),this['broadcastCompactionEvent'](_0x33495b,_0x3796b4,{'status':COMPACTION_STATUS[_0x54e14c(0x16a)],'strategy':_0x5e8b67,'messageCount':_0x404d0b[_0x54e14c(0x18b)]});let _0x3ee767=null,_0x1839ca=0x0;const _0x509dad=COMPACTION_CONFIG[_0x54e14c(0x10f)];while(_0x1839ca<_0x509dad&&!_0x3ee767){_0x1839ca++;try{const _0x638b94=_0x1839ca===0x1?_0x5e8b67:COMPACTION_STRATEGIES[_0x54e14c(0x10d)];_0x3ee767=await this[_0x54e14c(0x197)][_0x54e14c(0xcf)](_0x404d0b,_0x1b4ebc||_0x3465fe,_0x3465fe,{'strategy':_0x638b94,'targetTokenCount':this['tokenCountingService'][_0x54e14c(0xce)](_0x38f5a1),'sessionId':_0x3796b4});const _0x784a0b=this['tokenCountingService'][_0x54e14c(0x11d)](_0x4235a0,_0x3ee767[_0x54e14c(0x111)],_0x38f5a1);!_0x784a0b[_0x54e14c(0x1d8)]&&(this[_0x54e14c(0x108)][_0x54e14c(0x1b3)]('Compaction\x20validation\x20failed\x20for\x20agent\x20'+_0x33495b,{'attempt':_0x1839ca,'reason':_0x784a0b[_0x54e14c(0x10b)],'reductionPercent':_0x784a0b['reductionPercent']}),_0x1839ca<_0x509dad&&(_0x3ee767=null,await new Promise(_0x418557=>setTimeout(_0x418557,COMPACTION_CONFIG['RETRY_DELAY_MS']))));}catch(_0x245186){this['logger']['error'](_0x54e14c(0xe7)+_0x1839ca+'\x20failed\x20for\x20agent\x20'+_0x33495b,{'error':_0x245186['message']});if(_0x1839ca>=_0x509dad)throw _0x245186;await new Promise(_0x5b5a88=>setTimeout(_0x5b5a88,COMPACTION_CONFIG[_0x54e14c(0x1c0)]));}}if(!_0x3ee767)throw new Error(_0x54e14c(0x161));if(_0x1b4ebc&&_0x1b4ebc!==_0x3465fe&&_0x46f048===_0x1b4ebc){const _0xdff259=await this[_0x54e14c(0x12b)]['getCompactionMetadata'](_0x33495b,_0x1b4ebc);if(_0xdff259&&_0xdff259[_0x54e14c(0xe9)]){for(const _0x1ad33c of _0xdff259[_0x54e14c(0xe9)]){await this['agentPool']['addMessageToConversation'](_0x33495b,_0x3465fe,_0x1ad33c);}this['logger']['debug']('Copied\x20'+_0xdff259['originalMessages'][_0x54e14c(0x18b)]+_0x54e14c(0x1c7)+_0x1b4ebc+'\x20to\x20'+_0x3465fe+'\x20for\x20model\x20switching');}}return await this[_0x54e14c(0x12b)]['updateCompactedMessages'](_0x33495b,_0x3465fe,_0x3ee767),_0x101bfa&&console[_0x54e14c(0xf6)]('[COMPACT-COMPLETED]',{'agentId':_0x33495b,'strategy':_0x3ee767['strategy'],'originalMessageCount':_0x3ee767['originalMessages']?.[_0x54e14c(0x18b)]||0x0,'compactedMessageCount':_0x3ee767[_0x54e14c(0x143)]?.[_0x54e14c(0x18b)]||0x0,'originalTokens':_0x3ee767[_0x54e14c(0x18d)],'compactedTokens':_0x3ee767['compactedTokenCount'],'reductionPercent':_0x3ee767[_0x54e14c(0x1e2)]['toFixed'](0x1),'executionTimeMs':_0x3ee767[_0x54e14c(0x156)],'model':_0x3465fe}),this[_0x54e14c(0x108)][_0x54e14c(0xd6)](_0x54e14c(0x185)+_0x33495b,{'strategy':_0x3ee767['strategy'],'originalTokens':_0x3ee767['originalTokenCount'],'compactedTokens':_0x3ee767[_0x54e14c(0x111)],'reduction':_0x3ee767[_0x54e14c(0x1e2)][_0x54e14c(0x16f)](0x1)+'%','executionTime':_0x3ee767[_0x54e14c(0x156)]+'ms'}),this[_0x54e14c(0x1ca)]['delete'](_0x33495b),this[_0x54e14c(0xea)](_0x33495b,_0x3796b4,{'status':COMPACTION_STATUS['COMPLETED'],'originalTokens':_0x3ee767['originalTokenCount'],'compactedTokens':_0x3ee767['compactedTokenCount'],'reductionPercent':_0x3ee767['reductionPercent'],'strategy':_0x3ee767['strategy'],'executionTime':_0x3ee767[_0x54e14c(0x156)]}),{'shouldContinue':!![],'compactionPerformed':!![]};}catch(_0x210dbf){return this['logger']['error']('Compaction\x20failed\x20for\x20agent\x20'+_0x33495b,{'error':_0x210dbf['message'],'stack':_0x210dbf[_0x54e14c(0x126)]}),this[_0x54e14c(0x1ca)]['delete'](_0x33495b),this['broadcastCompactionEvent'](_0x33495b,_0x3796b4,{'status':COMPACTION_STATUS['FAILED'],'error':_0x210dbf[_0x54e14c(0x12f)]}),{'shouldContinue':!![],'error':_0x210dbf['message']};}}['broadcastCompactionEvent'](_0x55e832,_0x32a67d,_0x344e22){const _0x6052d1=a0_0x567dbc;if(!this['webSocketManager']||!this[_0x6052d1(0x1b7)]['broadcastToSession'])return;this['webSocketManager'][_0x6052d1(0x1c4)](_0x32a67d,{'type':_0x6052d1(0x15c),'data':{'agentId':_0x55e832,'timestamp':new Date()[_0x6052d1(0x1cf)](),..._0x344e22}});}async['getAgentAIResponse'](_0x418c89){const _0x18dcf2=a0_0x567dbc;try{const _0x70b92a=await this[_0x18dcf2(0x12b)]['getAgent'](_0x418c89);if(!_0x70b92a)return null;const _0x5035ca=_0x70b92a[_0x18dcf2(0x1cb)]?.['full']?.[_0x18dcf2(0x176)]||[],_0x4d0670=this['activeAgents'][_0x18dcf2(0x1cd)](_0x418c89),_0xc3f448=_0x4d0670?.['sessionId']||_0x70b92a[_0x18dcf2(0x1d1)];if(!_0xc3f448)return this['logger']['error'](_0x18dcf2(0x15f)+_0x418c89+_0x18dcf2(0x188),{'agentName':_0x70b92a['name'],'hasAgentContext':!!_0x4d0670,'agentSessionId':_0x70b92a[_0x18dcf2(0x1d1)],'contextSessionId':_0x4d0670?.[_0x18dcf2(0x1d1)]}),null;let _0x39e493=_0x70b92a['currentModel'];if(!_0x39e493){this['logger'][_0x18dcf2(0x1b3)]('Agent\x20'+_0x418c89+'\x20has\x20no\x20currentModel\x20set,\x20using\x20preferredModel\x20as\x20fallback',{'agentId':_0x418c89,'preferredModel':_0x70b92a[_0x18dcf2(0x10a)],'availableConversations':Object[_0x18dcf2(0xf5)](_0x70b92a[_0x18dcf2(0x1cb)]||{})});this[_0x18dcf2(0x1b7)]&&_0xc3f448&&this[_0x18dcf2(0x1b7)]['broadcastToSession'](_0xc3f448,{'type':_0x18dcf2(0x1b8),'agentId':_0x418c89,'agentName':_0x70b92a['name'],'message':_0x18dcf2(0xed),'details':_0x18dcf2(0x19b)+_0x70b92a[_0x18dcf2(0x18f)]+_0x18dcf2(0x1a1)+(_0x70b92a['preferredModel']||'default model')+'.','severity':'warning','timestamp':new Date()[_0x18dcf2(0x1cf)]()});_0x39e493=_0x70b92a['preferredModel'];if(_0x39e493)_0x70b92a[_0x18dcf2(0x107)]=_0x39e493,await this['agentPool']['persistAgentState'](_0x418c89),this['logger']['info'](_0x18dcf2(0x19e)+_0x39e493);else return this['logger']['error'](_0x18dcf2(0x15f)+_0x418c89+_0x18dcf2(0x14d)),this[_0x18dcf2(0x1b7)]&&_0xc3f448&&this[_0x18dcf2(0x1b7)][_0x18dcf2(0x1c4)](_0xc3f448,{'type':_0x18dcf2(0x10c),'agentId':_0x418c89,'agentName':_0x70b92a[_0x18dcf2(0x18f)],'message':'Agent\x20model\x20configuration\x20error','details':_0x18dcf2(0x19b)+_0x70b92a[_0x18dcf2(0x18f)]+'\x22\x20has\x20no\x20valid\x20model\x20configuration.\x20Cannot\x20process\x20messages.','severity':'error','timestamp':new Date()[_0x18dcf2(0x1cf)]()}),null;}if(_0x70b92a['dynamicModelRouting']&&this[_0x18dcf2(0x119)])try{const _0x339589=[..._0x5035ca][_0x18dcf2(0xec)]()['find'](_0x12d041=>_0x12d041[_0x18dcf2(0x1dc)]===_0x18dcf2(0x148));if(_0x339589){let _0x1268fb=[];if(this['modelsService'])try{this[_0x18dcf2(0x108)][_0x18dcf2(0x134)]('ModelsService\x20type\x20check',{'hasModelsService':!!this[_0x18dcf2(0xf2)],'type':typeof this['modelsService'],'methods':Object[_0x18dcf2(0x166)](Object[_0x18dcf2(0x1bf)](this['modelsService']))});let _0x4d4b96=this['modelsService'][_0x18dcf2(0xe8)]();const _0x132c3a=!this[_0x18dcf2(0xf2)]['lastFetched']||this[_0x18dcf2(0xf2)]['lastFetched']&&Date['now']()-new Date(this['modelsService'][_0x18dcf2(0x1ce)])[_0x18dcf2(0x179)]()>0x5*0x3c*0x3e8;(!_0x4d4b96||_0x4d4b96[_0x18dcf2(0x18b)]===0x0||_0x132c3a)&&(this[_0x18dcf2(0x108)][_0x18dcf2(0xd6)]('Models list empty or stale, fetching from backend with sessionId'),await this[_0x18dcf2(0xf2)]['fetchModels']({'sessionId':_0xc3f448}),_0x4d4b96=this[_0x18dcf2(0xf2)][_0x18dcf2(0xe8)]()),_0x1268fb=_0x4d4b96['filter'](_0xa98370=>_0xa98370['id']!=='autopilot-model-router'&&_0xa98370[_0x18dcf2(0x18f)]!=='autopilot-model-router')['map'](_0x5065a4=>_0x5065a4['id']||_0x5065a4['name']),this['logger'][_0x18dcf2(0x134)]('Available\x20models\x20for\x20routing:\x20'+_0x1268fb[_0x18dcf2(0x139)](',\x20'));}catch(_0x1a88e2){this['logger']['warn']('Failed\x20to\x20get\x20available\x20models\x20for\x20routing:\x20'+_0x1a88e2[_0x18dcf2(0x12f)]);}const _0x102b4a=await this[_0x18dcf2(0x119)]['routeMessage'](_0x339589[_0x18dcf2(0x159)],_0x5035ca['slice'](-0x5),_0x70b92a[_0x18dcf2(0x107)],_0x1268fb,{'agentId':_0x418c89,'sessionId':_0xc3f448});this['logger'][_0x18dcf2(0xd6)]('Routing\x20result\x20analysis',{'selectedModel':_0x102b4a[_0x18dcf2(0x17b)],'currentModel':_0x70b92a['currentModel'],'areEqual':_0x102b4a[_0x18dcf2(0x17b)]===_0x70b92a['currentModel'],'willSwitch':_0x102b4a['selectedModel']&&_0x102b4a[_0x18dcf2(0x17b)]!==_0x70b92a['currentModel']}),_0x102b4a[_0x18dcf2(0x17b)]&&_0x102b4a['selectedModel']!==_0x70b92a['currentModel']?(this[_0x18dcf2(0x108)][_0x18dcf2(0xd6)](_0x18dcf2(0x1ac)+_0x70b92a['currentModel']+'\x20to\x20'+_0x102b4a['selectedModel'],{'agentId':_0x418c89,'reason':_0x102b4a[_0x18dcf2(0x1d2)]}),_0x39e493=_0x102b4a[_0x18dcf2(0x17b)],_0x70b92a[_0x18dcf2(0x107)]=_0x39e493,await this[_0x18dcf2(0x12b)][_0x18dcf2(0xca)](_0x418c89),this[_0x18dcf2(0x108)][_0x18dcf2(0xd6)]('Model\x20updated:\x20targetModel='+_0x39e493+_0x18dcf2(0x114)+_0x70b92a[_0x18dcf2(0x107)])):this['logger']['info']('No\x20model\x20switch\x20needed',{'selectedModel':_0x102b4a[_0x18dcf2(0x17b)],'currentModel':_0x70b92a['currentModel'],'hasSelectedModel':!!_0x102b4a[_0x18dcf2(0x17b)]});}}catch(_0x596d84){this['logger'][_0x18dcf2(0x1b3)](_0x18dcf2(0x144)+_0x596d84['message']);}this['logger']['info']('About\x20to\x20send\x20message\x20to\x20model:\x20'+_0x39e493,{'agentId':_0x418c89,'targetModel':_0x39e493,'originalModel':_0x70b92a[_0x18dcf2(0x107)]});const _0x3e2996=await this[_0x18dcf2(0x19f)](_0x418c89,_0x39e493,_0xc3f448);if(!_0x3e2996['shouldContinue'])return this['logger']['warn']('Compaction\x20check\x20returned\x20shouldContinue=false\x20for\x20agent\x20'+_0x418c89),null;_0x3e2996[_0x18dcf2(0x17a)]&&this[_0x18dcf2(0x108)]['info']('Compaction\x20performed\x20for\x20agent\x20'+_0x418c89+_0x18dcf2(0x1e3));const _0x1fdcac=await this['agentPool']['getMessagesForAI'](_0x418c89,_0x39e493);let _0x584f27=_0x70b92a[_0x18dcf2(0x1de)];if(_0x70b92a['mode']===AGENT_MODES[_0x18dcf2(0x178)]){const _0x82d69e=_0x18dcf2(0x1a5);_0x584f27=(_0x70b92a[_0x18dcf2(0x1de)]||'')+_0x82d69e;}try{const _0x42d9f0=await this[_0x18dcf2(0x1a2)][_0x18dcf2(0x194)](_0x418c89);_0x42d9f0&&(_0x584f27=(_0x584f27||'')+_0x42d9f0,this['logger'][_0x18dcf2(0x134)](_0x18dcf2(0x15b)+_0x418c89,{'contextLength':_0x42d9f0['length']}));}catch(_0x5919ab){this[_0x18dcf2(0x108)]['warn'](_0x18dcf2(0x14a)+_0x418c89,{'error':_0x5919ab[_0x18dcf2(0x12f)]});}const _0x4b1a9d=await this[_0x18dcf2(0x186)][_0x18dcf2(0xde)](_0x39e493,_0x1fdcac,{'agentId':_0x418c89,'systemPrompt':_0x584f27,'sessionId':_0xc3f448,'platformProvided':_0x70b92a['platformProvided']});return _0x4b1a9d;}catch(_0x1722ca){return this['logger']['error'](_0x18dcf2(0x1e5)+_0x418c89+':',_0x1722ca),await this['handleAIServiceFailure'](_0x418c89,_0x1722ca),null;}}async[a0_0x567dbc(0xe0)](_0x5a9ae5,_0x48d9b1){const _0x15427b=a0_0x567dbc,_0x6e846f=await this[_0x15427b(0x12b)]['getAgent'](_0x5a9ae5);if(!_0x6e846f)return;const _0x392821=_0x48d9b1[_0x15427b(0x12f)]?.['toLowerCase']()||'';if(_0x392821['includes'](_0x15427b(0x190))||_0x392821[_0x15427b(0x1c1)](_0x15427b(0x137)))this[_0x15427b(0x108)]['warn'](_0x15427b(0x15f)+_0x5a9ae5+_0x15427b(0x193)),_0x6e846f['delayEndTime']=new Date(Date[_0x15427b(0x187)]()+0x5*0x3c*0x3e8)[_0x15427b(0x1cf)](),await this['agentPool']['persistAgentState'](_0x5a9ae5),await this[_0x15427b(0x12b)][_0x15427b(0x1a3)](_0x5a9ae5,{'toolId':_0x15427b(0x12e),'status':'failed','error':_0x15427b(0x1af),'timestamp':new Date()['toISOString']()});else{if(_0x392821[_0x15427b(0x1c1)]('rate\x20limit')||_0x392821[_0x15427b(0x1c1)](_0x15427b(0x151)))this[_0x15427b(0x108)][_0x15427b(0x1b3)](_0x15427b(0x15f)+_0x5a9ae5+'\x20delayed\x20due\x20to\x20rate\x20limiting'),_0x6e846f[_0x15427b(0x1c9)]=new Date(Date[_0x15427b(0x187)]()+0x2*0x3c*0x3e8)[_0x15427b(0x1cf)](),await this[_0x15427b(0x12b)][_0x15427b(0xca)](_0x5a9ae5);else _0x392821['includes'](_0x15427b(0x1d6))||_0x392821['includes'](_0x15427b(0x1aa))?(this[_0x15427b(0x108)]['warn'](_0x15427b(0x15f)+_0x5a9ae5+'\x20delayed\x20due\x20to\x20network\x20issues'),_0x6e846f['delayEndTime']=new Date(Date['now']()+0x1e*0x3e8)[_0x15427b(0x1cf)](),await this[_0x15427b(0x12b)][_0x15427b(0xca)](_0x5a9ae5)):(this['logger']['error']('Agent\x20'+_0x5a9ae5+_0x15427b(0x149)+_0x48d9b1['message']),_0x6e846f['delayEndTime']=new Date(Date[_0x15427b(0x187)]()+0x1*0x3c*0x3e8)['toISOString'](),await this['agentPool']['persistAgentState'](_0x5a9ae5),await this['agentPool']['addToolResult'](_0x5a9ae5,{'toolId':'system-error','status':'failed','error':_0x15427b(0xf4)+_0x48d9b1['message']+'.\x20Agent\x20temporarily\x20paused.','timestamp':new Date()['toISOString']()}));}if(this[_0x15427b(0x1b7)]&&this['webSocketManager']['broadcastToSession']){const _0x9738c1=this[_0x15427b(0x198)]['get'](_0x5a9ae5),_0x55d8b9=_0x9738c1?.[_0x15427b(0x1d1)]||'scheduler-session';this[_0x15427b(0x1b7)][_0x15427b(0x1c4)](_0x55d8b9,{'type':'agent_error','data':{'agentId':_0x5a9ae5,'error':_0x48d9b1[_0x15427b(0x12f)],'recovery':'Agent\x20temporarily\x20paused\x20for\x20recovery','timestamp':new Date()['toISOString']()}});}}async['processAIResponse'](_0x594af2,_0x2e1367){const _0x5bf6a5=a0_0x567dbc,_0x5c3b94=this[_0x5bf6a5(0x198)][_0x5bf6a5(0x1cd)](_0x594af2),_0x3a1df4=_0x5c3b94?.['sessionId']||_0x5bf6a5(0x104),_0x59bc0c={'id':_0x5bf6a5(0x1bd)+Date['now'](),'agentId':_0x594af2,'role':MESSAGE_ROLES['ASSISTANT'],'content':_0x2e1367['content'],'timestamp':new Date()['toISOString'](),'model':_0x2e1367['model'],'tokenUsage':_0x2e1367[_0x5bf6a5(0x1c3)],'sessionId':_0x3a1df4};await this[_0x5bf6a5(0x1b0)](_0x594af2,_0x59bc0c,![]);let _0x263e21=[];try{const _0x5da23f=await this['messageProcessor']['extractAndExecuteTools'](_0x2e1367[_0x5bf6a5(0x159)],_0x594af2,{'sessionId':_0x3a1df4});if(_0x5da23f[_0x5bf6a5(0x18b)]>0x0){const _0x1cc54d=await this['agentPool']['getAgent'](_0x594af2);if(_0x1cc54d){for(const _0xf0d9cd of _0x5da23f){_0x1cc54d[_0x5bf6a5(0x173)]['toolResults'][_0x5bf6a5(0xd8)]({'id':_0x5bf6a5(0x11c)+Date[_0x5bf6a5(0x187)]()+'-'+Math[_0x5bf6a5(0x100)]()[_0x5bf6a5(0x1a7)](0x24)[_0x5bf6a5(0x168)](0x2,0x9),'toolId':_0xf0d9cd[_0x5bf6a5(0xe2)],'status':_0xf0d9cd[_0x5bf6a5(0x1db)],'result':_0xf0d9cd['result'],'error':_0xf0d9cd['error'],'executionTime':_0xf0d9cd['executionTime'],'timestamp':new Date()['toISOString'](),'queuedAt':new Date()['toISOString']()}),_0x263e21['push']({'toolId':_0xf0d9cd['toolId'],'status':_0xf0d9cd['status'],'error':_0xf0d9cd['error'],'executionTime':_0xf0d9cd['executionTime']});}await this['agentPool']['persistAgentState'](_0x594af2);}}}catch(_0x5b382a){this[_0x5bf6a5(0x108)][_0x5bf6a5(0xd7)]('Tool\x20execution\x20failed\x20for\x20agent\x20'+_0x594af2+':',_0x5b382a);}_0x263e21['length']>0x0&&(_0x59bc0c[_0x5bf6a5(0x174)]=_0x263e21,_0x59bc0c[_0x5bf6a5(0x13c)]=!![]);if(this[_0x5bf6a5(0xf8)](_0x59bc0c)){const _0x198713=await this['agentPool']['getAgent'](_0x594af2);this['broadcastMessageUpdate'](_0x594af2,_0x59bc0c,{'agentCurrentModel':_0x198713?.['currentModel']});}}['shouldAgentContinue'](_0x36e4f8,_0x19229f){const _0x4d0b72=a0_0x567dbc;if(!_0x19229f)return![];const _0x1540cc=_0x19229f[_0x4d0b72(0x173)]['toolResults'][_0x4d0b72(0xf9)](_0x337df0=>_0x337df0['toolId']==='jobdone'||_0x337df0['result']&&String(_0x337df0[_0x4d0b72(0x125)])['toLowerCase']()[_0x4d0b72(0x1c1)](_0x4d0b72(0x1b2)));if(_0x1540cc)return this['logger']['info']('Agent\x20'+_0x36e4f8+'\x20executed\x20jobdone\x20-\x20removing\x20from\x20scheduler'),![];if(_0x19229f['mode']===AGENT_MODES['CHAT']){const _0x611d15=_0x19229f[_0x4d0b72(0x173)][_0x4d0b72(0x11a)]['length']>0x0||_0x19229f[_0x4d0b72(0x173)][_0x4d0b72(0x128)][_0x4d0b72(0x18b)]>0x0;return!_0x611d15&&this[_0x4d0b72(0x108)][_0x4d0b72(0x134)](_0x4d0b72(0x18c)+_0x36e4f8+_0x4d0b72(0x1b6),{'toolResults':_0x19229f[_0x4d0b72(0x173)][_0x4d0b72(0x1e6)][_0x4d0b72(0x18b)],'userMessages':_0x19229f[_0x4d0b72(0x173)]['userMessages']['length'],'interAgentMessages':_0x19229f[_0x4d0b72(0x173)][_0x4d0b72(0x128)]['length']}),_0x611d15;}if(_0x19229f[_0x4d0b72(0x167)]===AGENT_MODES[_0x4d0b72(0x178)])return!_0x19229f[_0x4d0b72(0x154)];return![];}[a0_0x567dbc(0x15e)](_0x18fef0){const _0x2546e1=a0_0x567dbc;if(_0x18fef0['status']===_0x2546e1(0x191)){if(typeof _0x18fef0[_0x2546e1(0x125)]==='object')return JSON[_0x2546e1(0xd4)](_0x18fef0[_0x2546e1(0x125)],null,0x2);return String(_0x18fef0[_0x2546e1(0x125)]||'Tool\x20executed\x20successfully');}else{if(_0x18fef0[_0x2546e1(0x1db)]===_0x2546e1(0x1b9))return _0x2546e1(0x17d)+(_0x18fef0[_0x2546e1(0xd7)]||'Unknown\x20error');}return'Tool\x20status:\x20'+_0x18fef0['status'];}[a0_0x567dbc(0xf8)](_0x5528a6){const _0x4ad748=a0_0x567dbc;if(_0x5528a6['type']===_0x4ad748(0xe1))return![];if(_0x5528a6['role']===MESSAGE_ROLES['SYSTEM']&&!_0x5528a6[_0x4ad748(0x1c8)])return![];return!![];}['broadcastMessageUpdate'](_0x2a766c,_0x181f16,_0x4f2d08={}){const _0x821af5=a0_0x567dbc;if(this['webSocketManager']&&this[_0x821af5(0x1b7)][_0x821af5(0x1c4)]){const _0x3ea9cc=this['activeAgents'][_0x821af5(0x1cd)](_0x2a766c);let _0x579c1b=_0x3ea9cc?.[_0x821af5(0x1d1)];!_0x579c1b&&_0x181f16[_0x821af5(0x1d1)]&&(_0x579c1b=_0x181f16['sessionId']),!_0x579c1b&&(_0x579c1b=_0x821af5(0x104)),this[_0x821af5(0x108)][_0x821af5(0xd6)]('Broadcasting\x20message\x20to\x20session',{'agentId':_0x2a766c,'sessionId':_0x579c1b,'hasAgentContext':!!_0x3ea9cc,'agentContextSessionId':_0x3ea9cc?.[_0x821af5(0x1d1)],'messageSessionId':_0x181f16['sessionId'],'messageRole':_0x181f16[_0x821af5(0x1dc)],'messageType':_0x181f16[_0x821af5(0x136)]}),this['webSocketManager'][_0x821af5(0x1c4)](_0x579c1b,{'type':_0x821af5(0x196),'data':{'agentId':_0x2a766c,'message':_0x181f16,'timestamp':new Date()['toISOString'](),'agentCurrentModel':_0x4f2d08['agentCurrentModel']}});}}['hasPendingTasks'](_0x2c4a5f){const _0x5df508=a0_0x567dbc;if(!_0x2c4a5f['taskList']||!_0x2c4a5f[_0x5df508(0xe4)]['tasks'])return![];return _0x2c4a5f['taskList']['tasks']['some'](_0x4bcce3=>_0x4bcce3['status']==='pending'||_0x4bcce3['status']===_0x5df508(0x138));}[a0_0x567dbc(0xc8)](_0x205c1f){const _0x386748=a0_0x567dbc;if(_0x205c1f[_0x386748(0x1da)]&&_0x205c1f[_0x386748(0x1da)]['length']>0x0)return!![];if(_0x205c1f['interAgentTracking']&&_0x205c1f[_0x386748(0x13a)][_0x386748(0x1c5)]>0x0){const _0x428288=Date['now'](),_0x392e7c=0xa*0x3c*0x3e8;for(const _0x2512a8 of _0x205c1f[_0x386748(0x13a)]['values']()){if(_0x2512a8[_0x386748(0x145)]&&_0x428288-_0x2512a8[_0x386748(0x145)]<_0x392e7c&&_0x2512a8[_0x386748(0x12a)]===_0x386748(0x169))return!![];}}return![];}async[a0_0x567dbc(0x165)](_0x5985cd){const _0x2ef2ed=a0_0x567dbc;try{const _0x4add23=await this['agentPool']['getAgent'](_0x5985cd);if(!_0x4add23||_0x4add23['mode']!==AGENT_MODES['AGENT'])return;!_0x4add23['taskList']&&(_0x4add23['taskList']={'tasks':[],'lastUpdated':new Date()[_0x2ef2ed(0x1cf)]()});if(_0x4add23[_0x2ef2ed(0xe4)]['tasks']&&_0x4add23[_0x2ef2ed(0xe4)][_0x2ef2ed(0x1e7)]['length']>0x0)return;const _0xd94d6c=_0x4add23['conversations']?.['full']?.[_0x2ef2ed(0x176)]||[],_0x3e8ddf=[..._0xd94d6c]['reverse']()[_0x2ef2ed(0xe6)](_0x4cef0f=>_0x4cef0f['role']===MESSAGE_ROLES['USER']);if(_0x3e8ddf){const _0xa7b02c=_0x2ef2ed(0x122)+this['extractTaskTitle'](_0x3e8ddf[_0x2ef2ed(0x159)]),_0x599f48=_0x2ef2ed(0x15d)+this[_0x2ef2ed(0x180)](_0x3e8ddf[_0x2ef2ed(0x159)],0xc8)+'\x22',_0x3e7ca1={'id':_0x2ef2ed(0x18e)+Date['now']()+'-'+Math['random']()[_0x2ef2ed(0x1a7)](0x24)[_0x2ef2ed(0x168)](0x2,0x9),'title':_0xa7b02c,'description':_0x599f48,'status':'pending','priority':'high','createdAt':new Date()[_0x2ef2ed(0x1cf)](),'updatedAt':new Date()['toISOString'](),'source':'auto-created-initial','messageId':_0x3e8ddf['id']};_0x4add23[_0x2ef2ed(0xe4)]['tasks']['push'](_0x3e7ca1),_0x4add23[_0x2ef2ed(0xe4)][_0x2ef2ed(0x153)]=new Date()[_0x2ef2ed(0x1cf)](),await this['agentPool']['persistAgentState'](_0x5985cd),this[_0x2ef2ed(0x108)]['info'](_0x2ef2ed(0x172)+_0x5985cd,{'taskId':_0x3e7ca1['id'],'title':_0x3e7ca1['title'],'agentName':_0x4add23[_0x2ef2ed(0x18f)]});}}catch(_0x308350){this[_0x2ef2ed(0x108)][_0x2ef2ed(0xd7)]('Failed\x20to\x20auto-create\x20initial\x20task\x20for\x20agent\x20'+_0x5985cd,{'error':_0x308350['message']});}}async[a0_0x567dbc(0x160)](_0x2aa042,_0x632c76,_0x4a28e5){const _0x51d6f2=a0_0x567dbc;try{const _0x217d00=await this[_0x51d6f2(0x12b)][_0x51d6f2(0x129)](_0x2aa042);if(!_0x217d00||_0x217d00['mode']!==AGENT_MODES['AGENT'])return;!_0x217d00['taskList']&&(_0x217d00[_0x51d6f2(0xe4)]={'tasks':[],'lastUpdated':new Date()['toISOString']()});for(const _0x376ae6 of _0x632c76){const _0x306b75=_0x51d6f2(0x182)+this[_0x51d6f2(0xf0)](_0x376ae6['content']),_0x1e7172='Handle\x20user\x20message:\x20\x22'+this[_0x51d6f2(0x180)](_0x376ae6['content'],0xc8)+'\x22',_0x473c72=_0x217d00['taskList']['tasks'][_0x51d6f2(0xe6)](_0x30c5e2=>_0x30c5e2[_0x51d6f2(0x1db)]==='pending'&&_0x30c5e2['title'][_0x51d6f2(0x1c1)](_0x51d6f2(0xee))&&this['calculateContentSimilarity'](_0x30c5e2['description'],_0x1e7172)>0.7);if(!_0x473c72){const _0x462329={'id':_0x51d6f2(0x12c)+Date['now']()+'-'+Math['random']()['toString'](0x24)[_0x51d6f2(0x168)](0x2,0x9),'title':_0x306b75,'description':_0x1e7172,'status':'pending','priority':'high','createdAt':new Date()[_0x51d6f2(0x1cf)](),'updatedAt':new Date()['toISOString'](),'source':'auto-created','messageId':_0x376ae6['id']};_0x217d00[_0x51d6f2(0xe4)]['tasks']['push'](_0x462329),this['logger']?.[_0x51d6f2(0xd6)](_0x51d6f2(0x171),{'agentId':_0x2aa042,'taskId':_0x462329['id'],'title':_0x462329[_0x51d6f2(0x102)]});}}for(const _0x21fd79 of _0x4a28e5){const _0x1ff5f0=_0x21fd79['senderName']||_0x21fd79[_0x51d6f2(0x105)]||'Unknown\x20Agent',_0xaa5488=_0x51d6f2(0x177)+_0x1ff5f0+':\x20'+this['extractTaskTitle'](_0x21fd79['content']),_0x488773=_0x51d6f2(0xfe)+_0x1ff5f0+':\x20\x22'+this[_0x51d6f2(0x180)](_0x21fd79[_0x51d6f2(0x159)],0xc8)+'\x22',_0x46cb01=_0x217d00['taskList'][_0x51d6f2(0x1e7)]['find'](_0x204b47=>_0x204b47[_0x51d6f2(0x1db)]==='pending'&&_0x204b47[_0x51d6f2(0x102)]['includes'](_0x51d6f2(0x177)+_0x1ff5f0)&&this[_0x51d6f2(0x164)](_0x204b47[_0x51d6f2(0x19c)],_0x488773)>0.7);if(!_0x46cb01){const _0x27771f={'id':_0x51d6f2(0x12c)+Date['now']()+'-'+Math[_0x51d6f2(0x100)]()['toString'](0x24)[_0x51d6f2(0x168)](0x2,0x9),'title':_0xaa5488,'description':_0x488773,'status':_0x51d6f2(0x1dd),'priority':'medium','createdAt':new Date()['toISOString'](),'updatedAt':new Date()['toISOString'](),'source':_0x51d6f2(0x1b5),'messageId':_0x21fd79['id'],'senderAgent':_0x21fd79['sender']};_0x217d00[_0x51d6f2(0xe4)]['tasks']['push'](_0x27771f),this['logger']?.[_0x51d6f2(0xd6)](_0x51d6f2(0x199),{'agentId':_0x2aa042,'taskId':_0x27771f['id'],'title':_0x27771f[_0x51d6f2(0x102)],'sender':_0x1ff5f0});}}(_0x632c76[_0x51d6f2(0x18b)]>0x0||_0x4a28e5[_0x51d6f2(0x18b)]>0x0)&&(_0x217d00[_0x51d6f2(0xe4)][_0x51d6f2(0x153)]=new Date()[_0x51d6f2(0x1cf)](),await this[_0x51d6f2(0x12b)][_0x51d6f2(0xca)](_0x2aa042));}catch(_0x1d971f){this[_0x51d6f2(0x108)]?.[_0x51d6f2(0xd7)]('Failed\x20to\x20auto-create\x20tasks\x20for\x20agent\x20'+_0x2aa042,{'error':_0x1d971f[_0x51d6f2(0x12f)],'userMessageCount':_0x632c76['length'],'interAgentMessageCount':_0x4a28e5[_0x51d6f2(0x18b)]});}}['extractTaskTitle'](_0x4847f5){const _0x1a30e0=a0_0x567dbc,_0x57f20b=_0x4847f5['trim']()['replace'](/\n+/g,'\x20')[_0x1a30e0(0xdf)](/\s+/g,'\x20'),_0x56487d=_0x57f20b[_0x1a30e0(0xcc)](/[.!?]/)[0x0][_0x1a30e0(0x147)]();if(_0x56487d[_0x1a30e0(0x18b)]>0x32)return _0x56487d[_0x1a30e0(0x1ba)](0x0,0x2f)+_0x1a30e0(0xd3);return _0x56487d||_0x1a30e0(0x1c2);}['truncateContent'](_0x59415e,_0x53d2fb){const _0x39f91f=a0_0x567dbc;if(_0x59415e[_0x39f91f(0x18b)]<=_0x53d2fb)return _0x59415e;return _0x59415e[_0x39f91f(0x1ba)](0x0,_0x53d2fb-0x3)+_0x39f91f(0xd3);}['calculateContentSimilarity'](_0x3d239f,_0xe4319c){const _0x3d9056=a0_0x567dbc,_0x3f4b95=_0x3d239f['toLowerCase']()['split'](/\s+/),_0x13f7ed=_0xe4319c['toLowerCase']()[_0x3d9056(0xcc)](/\s+/),_0x2b2d8d=_0x3f4b95[_0x3d9056(0x16b)](_0x558ceb=>_0x13f7ed['includes'](_0x558ceb)),_0x168199=new Set([..._0x3f4b95,..._0x13f7ed])['size'];return _0x2b2d8d[_0x3d9056(0x18b)]/_0x168199;}async['autoProgressHighestPriorityTask'](_0x346d10){const _0x4665b6=a0_0x567dbc;try{const _0x15d26c=await this[_0x4665b6(0x12b)][_0x4665b6(0x129)](_0x346d10);if(!_0x15d26c||!_0x15d26c[_0x4665b6(0xe4)]||!_0x15d26c['taskList']['tasks'])return;const _0x967cf4={'urgent':0x0,'high':0x1,'medium':0x2,'low':0x3};let _0x599f76=_0x15d26c['taskList']['tasks']['filter'](_0x22ce11=>_0x22ce11['status']===_0x4665b6(0x1dd));if(_0x599f76[_0x4665b6(0x18b)]===0x0)return;_0x599f76=this[_0x4665b6(0x10e)](_0x15d26c[_0x4665b6(0xe4)]['tasks'],_0x599f76);if(_0x599f76['length']===0x0){this[_0x4665b6(0x108)]?.[_0x4665b6(0xd6)](_0x4665b6(0x11e)+_0x346d10);return;}_0x599f76['sort']((_0x25166b,_0x3db836)=>{const _0x5c7076=_0x4665b6;if(_0x25166b[_0x5c7076(0x183)]!==undefined&&_0x3db836['priorityScore']!==undefined){const _0x23f92d=_0x3db836[_0x5c7076(0x183)]-_0x25166b[_0x5c7076(0x183)];if(Math['abs'](_0x23f92d)>0.1)return _0x23f92d;}const _0x56a688=_0x967cf4[_0x25166b['priority']]-_0x967cf4[_0x3db836[_0x5c7076(0x1ae)]];if(_0x56a688!==0x0)return _0x56a688;return new Date(_0x25166b['createdAt'])-new Date(_0x3db836['createdAt']);});const _0x40d5e7=_0x599f76[0x0],_0x168a02=_0x15d26c['taskList'][_0x4665b6(0x1e7)]['filter'](_0x5eec82=>_0x5eec82[_0x4665b6(0x1db)]===_0x4665b6(0x138));_0x168a02['length']===0x0&&(_0x40d5e7[_0x4665b6(0x1db)]='in_progress',_0x40d5e7[_0x4665b6(0x1ad)]=new Date()[_0x4665b6(0x1cf)](),_0x40d5e7['startedAt']=new Date()[_0x4665b6(0x1cf)](),_0x15d26c[_0x4665b6(0xe4)]['lastUpdated']=new Date()['toISOString'](),await this['agentPool'][_0x4665b6(0xca)](_0x346d10),this[_0x4665b6(0x108)]?.['info']('Auto-progressed\x20task\x20to\x20in-progress',{'agentId':_0x346d10,'taskId':_0x40d5e7['id'],'title':_0x40d5e7[_0x4665b6(0x102)],'priority':_0x40d5e7[_0x4665b6(0x1ae)]}));}catch(_0x4d716b){this[_0x4665b6(0x108)]?.['error'](_0x4665b6(0xfc)+_0x346d10,{'error':_0x4d716b['message']});}}['filterAvailableTasks'](_0x2657f4,_0x1d067b){return _0x1d067b['filter'](_0x348d20=>{const _0xb83eef=a0_0x2d8a;if(!_0x348d20[_0xb83eef(0x162)]||_0x348d20[_0xb83eef(0x162)]['length']===0x0)return!![];const _0x510631=_0x348d20['dependencies'][_0xb83eef(0x16b)](_0x40295d=>_0x40295d['type']==='blocks');for(const _0x3b6bd3 of _0x510631){const _0xd0dbb6=_0x2657f4['find'](_0x1e3a8f=>_0x1e3a8f['id']===_0x3b6bd3['taskId']);if(!_0xd0dbb6||_0xd0dbb6[_0xb83eef(0x1db)]!=='completed')return![];}return!![];});}async['updateDependentTasks'](_0xcb40f5,_0x738320){const _0x4ac652=a0_0x567dbc;try{if(!_0xcb40f5['taskList']||!_0xcb40f5[_0x4ac652(0xe4)]['tasks'])return;let _0x539525=![];for(const _0x4c6e6f of _0xcb40f5[_0x4ac652(0xe4)][_0x4ac652(0x1e7)]){if(_0x4c6e6f['status']===_0x4ac652(0x170)&&_0x4c6e6f[_0x4ac652(0x162)]){const _0x5c850b=_0x4c6e6f[_0x4ac652(0x162)][_0x4ac652(0xe6)](_0x2d1491=>_0x2d1491['type']==='blocks'&&_0x2d1491[_0x4ac652(0x12d)]===_0x738320);if(_0x5c850b){const _0x170728=_0x4c6e6f['dependencies'][_0x4ac652(0xf9)](_0xfe1959=>{const _0x222118=_0x4ac652;if(_0xfe1959['type']!=='blocks')return![];const _0x519f88=_0xcb40f5[_0x222118(0xe4)][_0x222118(0x1e7)][_0x222118(0xe6)](_0x5da6e9=>_0x5da6e9['id']===_0xfe1959[_0x222118(0x12d)]);return _0x519f88&&_0x519f88[_0x222118(0x1db)]!==_0x222118(0x191);});!_0x170728&&(_0x4c6e6f[_0x4ac652(0x1db)]=_0x4ac652(0x1dd),_0x4c6e6f[_0x4ac652(0x1ad)]=new Date()['toISOString'](),_0x539525=!![],this[_0x4ac652(0x108)]?.['info'](_0x4ac652(0xf3),{'taskId':_0x4c6e6f['id'],'title':_0x4c6e6f['title'],'completedDependency':_0x738320}));}}}_0x539525&&(_0xcb40f5['taskList'][_0x4ac652(0x153)]=new Date()[_0x4ac652(0x1cf)](),await this['agentPool']['persistAgentState'](_0xcb40f5['id']));}catch(_0x41ad0d){this[_0x4ac652(0x108)]?.['error'](_0x4ac652(0x1e1)+_0xcb40f5['id'],{'error':_0x41ad0d[_0x4ac652(0x12f)],'completedTaskId':_0x738320});}}[a0_0x567dbc(0xd5)](_0x4a6558){const _0x43d1f6=a0_0x567dbc,_0x477197=[],_0x520569=_0x4a6558[_0x43d1f6(0x1cb)]?.[_0x43d1f6(0x15a)]?.['messages']||[],_0x121f02=_0x520569['filter'](_0x220d5a=>_0x220d5a[_0x43d1f6(0x1dc)]==='user'||_0x220d5a['role']===_0x43d1f6(0x1e0))[_0x43d1f6(0xff)](-0x5),_0x25fcaf=_0x121f02['map'](_0x19eb89=>_0x19eb89['role']+':'+_0x19eb89[_0x43d1f6(0x159)]?.[_0x43d1f6(0x1ba)](0x0,0x64))[_0x43d1f6(0x139)]('|');_0x477197[_0x43d1f6(0xd8)](_0x43d1f6(0x157)+_0x25fcaf);if(_0x4a6558[_0x43d1f6(0xe4)]?.[_0x43d1f6(0x1e7)]){const _0x1ac46e=_0x4a6558[_0x43d1f6(0xe4)]['tasks']['filter'](_0x3fb03c=>_0x3fb03c['status']==='pending'||_0x3fb03c['status']==='in_progress')[_0x43d1f6(0xef)](_0x3f095c=>_0x3f095c['id']+':'+_0x3f095c[_0x43d1f6(0x1db)])['sort']()['join'](',');_0x477197[_0x43d1f6(0xd8)]('tasks:'+_0x1ac46e);}const _0x5073b3=_0x4a6558['messageQueues']||{};_0x477197[_0x43d1f6(0xd8)]('queues:T'+(_0x5073b3[_0x43d1f6(0x1e6)]?.[_0x43d1f6(0x18b)]||0x0)+':I'+(_0x5073b3['interAgentMessages']?.['length']||0x0)+':U'+(_0x5073b3[_0x43d1f6(0x11a)]?.['length']||0x0));const _0x5f2586=_0x477197['join']('||');let _0x290771=0x0;for(let _0x5a7e11=0x0;_0x5a7e11<_0x5f2586[_0x43d1f6(0x18b)];_0x5a7e11++){const _0x1d16b2=_0x5f2586['charCodeAt'](_0x5a7e11);_0x290771=(_0x290771<<0x5)-_0x290771+_0x1d16b2,_0x290771=_0x290771&_0x290771;}return _0x290771+'_'+_0x5f2586[_0x43d1f6(0x18b)];}[a0_0x567dbc(0x181)](_0x4d5dff,_0x4751a5){const _0x37c1ff=a0_0x567dbc,_0x581d68=this[_0x37c1ff(0xdd)]['get'](_0x4d5dff);return _0x581d68?_0x581d68[_0x37c1ff(0x1be)](_0x4751a5):![];}[a0_0x567dbc(0xe5)](_0x36c58c,_0xbbee71){const _0x1e6071=a0_0x567dbc;!this['processedStateHashes'][_0x1e6071(0x1be)](_0x36c58c)&&this['processedStateHashes']['set'](_0x36c58c,new Set());const _0x4b524f=this['processedStateHashes']['get'](_0x36c58c);_0x4b524f[_0x1e6071(0x13f)](_0xbbee71);if(_0x4b524f['size']>0x64){const _0x52b6df=Array['from'](_0x4b524f),_0x3b7185=_0x52b6df['slice'](-0x32);this['processedStateHashes'][_0x1e6071(0x16c)](_0x36c58c,new Set(_0x3b7185));}}[a0_0x567dbc(0x17e)](){const _0x4f8f3e=a0_0x567dbc;return{'isRunning':this[_0x4f8f3e(0x106)],'activeAgents':Array['from'](this[_0x4f8f3e(0x198)]),'agentCount':this['activeAgents'][_0x4f8f3e(0x1c5)]};}}export default AgentScheduler;
|