@loxia-labs/loxia-autopilot-one 1.0.1 → 1.0.4
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 +15 -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
package/src/core/stateManager.js
CHANGED
|
@@ -1,877 +1 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* StateManager - Handles state persistence, recovery, and project state management
|
|
3
|
-
*
|
|
4
|
-
* Purpose:
|
|
5
|
-
* - Project state persistence and recovery
|
|
6
|
-
* - Agent state management across sessions
|
|
7
|
-
* - Multi-model conversation state handling
|
|
8
|
-
* - Context reference state management
|
|
9
|
-
* - Session recovery and resume functionality
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
import { promises as fs } from 'fs';
|
|
13
|
-
import path from 'path';
|
|
14
|
-
|
|
15
|
-
class StateManager {
|
|
16
|
-
constructor(config, logger) {
|
|
17
|
-
this.config = config;
|
|
18
|
-
this.logger = logger;
|
|
19
|
-
|
|
20
|
-
this.stateDirectory = config.system?.stateDirectory || '.loxia-state';
|
|
21
|
-
this.stateVersion = '1.0.0';
|
|
22
|
-
|
|
23
|
-
// State file paths
|
|
24
|
-
this.stateFiles = {
|
|
25
|
-
projectState: 'project-state.json',
|
|
26
|
-
agentIndex: 'agent-index.json',
|
|
27
|
-
conversationIndex: 'conversation-index.json',
|
|
28
|
-
lastSession: 'last-session.json',
|
|
29
|
-
contextReferences: 'context-references.json',
|
|
30
|
-
asyncOperations: 'operations/async-operations.json',
|
|
31
|
-
pausedAgents: 'operations/paused-agents.json',
|
|
32
|
-
toolHistory: 'operations/tool-history.json',
|
|
33
|
-
modelRouterCache: 'models/model-router-cache.json',
|
|
34
|
-
errorRecoveryLog: 'models/error-recovery-log.json'
|
|
35
|
-
};
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* Initialize state directory structure
|
|
40
|
-
* @param {string} projectDir - Project directory path
|
|
41
|
-
* @returns {Promise<void>}
|
|
42
|
-
*/
|
|
43
|
-
async initializeStateDirectory(projectDir) {
|
|
44
|
-
const stateDir = path.join(projectDir, this.stateDirectory);
|
|
45
|
-
|
|
46
|
-
try {
|
|
47
|
-
// Create main state directory
|
|
48
|
-
await fs.mkdir(stateDir, { recursive: true });
|
|
49
|
-
|
|
50
|
-
// Create subdirectories
|
|
51
|
-
await fs.mkdir(path.join(stateDir, 'agents'), { recursive: true });
|
|
52
|
-
await fs.mkdir(path.join(stateDir, 'operations'), { recursive: true });
|
|
53
|
-
await fs.mkdir(path.join(stateDir, 'models'), { recursive: true });
|
|
54
|
-
|
|
55
|
-
this.logger.info(`State directory initialized: ${stateDir}`);
|
|
56
|
-
|
|
57
|
-
} catch (error) {
|
|
58
|
-
this.logger.error(`Failed to initialize state directory: ${error.message}`);
|
|
59
|
-
throw error;
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
* Resume project from saved state
|
|
65
|
-
* @param {string} projectDir - Project directory path
|
|
66
|
-
* @returns {Promise<Object>} Resumed project state
|
|
67
|
-
*/
|
|
68
|
-
async resumeProject(projectDir) {
|
|
69
|
-
try {
|
|
70
|
-
await this.initializeStateDirectory(projectDir);
|
|
71
|
-
|
|
72
|
-
// Load project state
|
|
73
|
-
const projectState = await this.loadProjectState(projectDir);
|
|
74
|
-
const agentIndex = await this.loadAgentIndex(projectDir);
|
|
75
|
-
|
|
76
|
-
// Restore agents with multi-model conversations
|
|
77
|
-
const restoredAgents = [];
|
|
78
|
-
for (const [agentId, agentInfo] of Object.entries(agentIndex)) {
|
|
79
|
-
try {
|
|
80
|
-
const agent = await this.restoreAgent(agentId, agentInfo, projectDir);
|
|
81
|
-
restoredAgents.push(agent);
|
|
82
|
-
} catch (error) {
|
|
83
|
-
this.logger.warn(`Failed to restore agent: ${agentId}`, error.message);
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
// Restore async operations
|
|
88
|
-
const asyncOperations = await this.restoreAsyncOperations(projectDir);
|
|
89
|
-
|
|
90
|
-
// Restore paused agents
|
|
91
|
-
const pausedAgents = await this.restorePausedAgents(projectDir);
|
|
92
|
-
|
|
93
|
-
// Restore context references
|
|
94
|
-
const contextReferences = await this.restoreContextReferences(projectDir);
|
|
95
|
-
|
|
96
|
-
const resumedState = {
|
|
97
|
-
projectState,
|
|
98
|
-
agents: restoredAgents,
|
|
99
|
-
asyncOperations,
|
|
100
|
-
pausedAgents,
|
|
101
|
-
contextReferences,
|
|
102
|
-
resumedSuccessfully: true,
|
|
103
|
-
resumedAt: new Date().toISOString()
|
|
104
|
-
};
|
|
105
|
-
|
|
106
|
-
// Update last session
|
|
107
|
-
await this.saveLastSession(projectDir, {
|
|
108
|
-
resumedAt: new Date().toISOString(),
|
|
109
|
-
agentCount: restoredAgents.length,
|
|
110
|
-
operationCount: asyncOperations.length
|
|
111
|
-
});
|
|
112
|
-
|
|
113
|
-
this.logger.info(`Project resumed successfully`, {
|
|
114
|
-
projectDir,
|
|
115
|
-
agentCount: restoredAgents.length,
|
|
116
|
-
operationCount: asyncOperations.length
|
|
117
|
-
});
|
|
118
|
-
|
|
119
|
-
return resumedState;
|
|
120
|
-
|
|
121
|
-
} catch (error) {
|
|
122
|
-
this.logger.error(`Project resume failed: ${error.message}`, {
|
|
123
|
-
projectDir,
|
|
124
|
-
error: error.stack
|
|
125
|
-
});
|
|
126
|
-
|
|
127
|
-
return {
|
|
128
|
-
projectState: null,
|
|
129
|
-
agents: [],
|
|
130
|
-
asyncOperations: [],
|
|
131
|
-
pausedAgents: [],
|
|
132
|
-
contextReferences: [],
|
|
133
|
-
resumedSuccessfully: false,
|
|
134
|
-
error: error.message
|
|
135
|
-
};
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
/**
|
|
140
|
-
* Persist agent state to storage
|
|
141
|
-
* @param {Object} agent - Agent object to persist
|
|
142
|
-
* @param {string} projectDir - Project directory path
|
|
143
|
-
* @returns {Promise<void>}
|
|
144
|
-
*/
|
|
145
|
-
async persistAgentState(agent, projectDir = process.cwd()) {
|
|
146
|
-
const stateDir = path.join(projectDir, this.stateDirectory);
|
|
147
|
-
const agentStateFile = path.join(stateDir, 'agents', `agent-${agent.id}-state.json`);
|
|
148
|
-
const agentConversationsFile = path.join(stateDir, 'agents', `agent-${agent.id}-conversations.json`);
|
|
149
|
-
|
|
150
|
-
try {
|
|
151
|
-
// Separate conversations from main agent state
|
|
152
|
-
const { conversations, ...agentState } = agent;
|
|
153
|
-
|
|
154
|
-
// Save agent state
|
|
155
|
-
await this.saveJSON(agentStateFile, {
|
|
156
|
-
version: this.stateVersion,
|
|
157
|
-
agentId: agent.id,
|
|
158
|
-
state: agentState,
|
|
159
|
-
lastPersisted: new Date().toISOString()
|
|
160
|
-
});
|
|
161
|
-
|
|
162
|
-
// Save conversations separately
|
|
163
|
-
await this.saveJSON(agentConversationsFile, {
|
|
164
|
-
version: this.stateVersion,
|
|
165
|
-
agentId: agent.id,
|
|
166
|
-
conversations,
|
|
167
|
-
lastPersisted: new Date().toISOString()
|
|
168
|
-
});
|
|
169
|
-
|
|
170
|
-
// Update agent index
|
|
171
|
-
await this.updateAgentIndex(agent, projectDir);
|
|
172
|
-
|
|
173
|
-
this.logger.debug(`Agent state persisted: ${agent.id}`);
|
|
174
|
-
|
|
175
|
-
} catch (error) {
|
|
176
|
-
this.logger.error(`Failed to persist agent state: ${error.message}`, {
|
|
177
|
-
agentId: agent.id,
|
|
178
|
-
error: error.stack
|
|
179
|
-
});
|
|
180
|
-
throw error;
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
/**
|
|
185
|
-
* Get project state
|
|
186
|
-
* @param {string} projectDir - Project directory path
|
|
187
|
-
* @returns {Promise<Object>} Project state object
|
|
188
|
-
*/
|
|
189
|
-
async getProjectState(projectDir) {
|
|
190
|
-
return await this.loadProjectState(projectDir);
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
/**
|
|
194
|
-
* Load project state from storage
|
|
195
|
-
* @param {string} projectDir - Project directory path
|
|
196
|
-
* @returns {Promise<Object>} Project state object
|
|
197
|
-
*/
|
|
198
|
-
async loadProjectState(projectDir) {
|
|
199
|
-
const stateFile = path.join(projectDir, this.stateDirectory, this.stateFiles.projectState);
|
|
200
|
-
|
|
201
|
-
try {
|
|
202
|
-
const data = await this.loadJSON(stateFile);
|
|
203
|
-
return data;
|
|
204
|
-
} catch (error) {
|
|
205
|
-
// Return default project state if file doesn't exist
|
|
206
|
-
const defaultState = {
|
|
207
|
-
version: this.stateVersion,
|
|
208
|
-
projectDir,
|
|
209
|
-
createdAt: new Date().toISOString(),
|
|
210
|
-
lastModified: new Date().toISOString(),
|
|
211
|
-
activeAgents: [],
|
|
212
|
-
lastActiveSession: null,
|
|
213
|
-
configuration: {
|
|
214
|
-
defaultModel: this.config.system?.defaultModel || 'anthropic-sonnet',
|
|
215
|
-
allowedTools: ['terminal', 'filesystem', 'browser'],
|
|
216
|
-
budgetLimit: 100.00
|
|
217
|
-
}
|
|
218
|
-
};
|
|
219
|
-
|
|
220
|
-
await this.saveProjectState(projectDir, defaultState);
|
|
221
|
-
return defaultState;
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
/**
|
|
226
|
-
* Save project state to storage
|
|
227
|
-
* @param {string} projectDir - Project directory path
|
|
228
|
-
* @param {Object} projectState - Project state object
|
|
229
|
-
* @returns {Promise<void>}
|
|
230
|
-
*/
|
|
231
|
-
async saveProjectState(projectDir, projectState) {
|
|
232
|
-
const stateFile = path.join(projectDir, this.stateDirectory, this.stateFiles.projectState);
|
|
233
|
-
|
|
234
|
-
const stateData = {
|
|
235
|
-
...projectState,
|
|
236
|
-
lastModified: new Date().toISOString()
|
|
237
|
-
};
|
|
238
|
-
|
|
239
|
-
await this.saveJSON(stateFile, stateData);
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
/**
|
|
243
|
-
* Load agent index
|
|
244
|
-
* @param {string} projectDir - Project directory path
|
|
245
|
-
* @returns {Promise<Object>} Agent index object
|
|
246
|
-
*/
|
|
247
|
-
async loadAgentIndex(projectDir) {
|
|
248
|
-
const indexFile = path.join(projectDir, this.stateDirectory, this.stateFiles.agentIndex);
|
|
249
|
-
|
|
250
|
-
try {
|
|
251
|
-
return await this.loadJSON(indexFile);
|
|
252
|
-
} catch (error) {
|
|
253
|
-
return {}; // Return empty index if file doesn't exist
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
/**
|
|
258
|
-
* Update agent index
|
|
259
|
-
* @param {Object} agent - Agent object
|
|
260
|
-
* @param {string} projectDir - Project directory path
|
|
261
|
-
* @returns {Promise<void>}
|
|
262
|
-
*/
|
|
263
|
-
async updateAgentIndex(agent, projectDir) {
|
|
264
|
-
const indexFile = path.join(projectDir, this.stateDirectory, this.stateFiles.agentIndex);
|
|
265
|
-
|
|
266
|
-
let agentIndex;
|
|
267
|
-
try {
|
|
268
|
-
agentIndex = await this.loadJSON(indexFile);
|
|
269
|
-
} catch {
|
|
270
|
-
agentIndex = {};
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
agentIndex[agent.id] = {
|
|
274
|
-
name: agent.name,
|
|
275
|
-
type: agent.type,
|
|
276
|
-
stateFile: `agents/agent-${agent.id}-state.json`,
|
|
277
|
-
conversationsFile: `agents/agent-${agent.id}-conversations.json`,
|
|
278
|
-
lastActivity: agent.lastActivity,
|
|
279
|
-
model: agent.currentModel,
|
|
280
|
-
status: agent.status
|
|
281
|
-
};
|
|
282
|
-
|
|
283
|
-
await this.saveJSON(indexFile, agentIndex);
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
/**
|
|
287
|
-
* Restore agent from saved state
|
|
288
|
-
* @param {string} agentId - Agent identifier
|
|
289
|
-
* @param {Object} agentInfo - Agent info from index
|
|
290
|
-
* @param {string} projectDir - Project directory path
|
|
291
|
-
* @returns {Promise<Object>} Restored agent object
|
|
292
|
-
*/
|
|
293
|
-
async restoreAgent(agentId, agentInfo, projectDir) {
|
|
294
|
-
const stateDir = path.join(projectDir, this.stateDirectory);
|
|
295
|
-
const stateFile = path.join(stateDir, agentInfo.stateFile);
|
|
296
|
-
const conversationsFile = path.join(stateDir, agentInfo.conversationsFile);
|
|
297
|
-
|
|
298
|
-
try {
|
|
299
|
-
// Load agent state
|
|
300
|
-
const stateData = await this.loadJSON(stateFile);
|
|
301
|
-
const conversationsData = await this.loadJSON(conversationsFile);
|
|
302
|
-
|
|
303
|
-
// Validate model conversations integrity
|
|
304
|
-
await this.validateModelConversations(conversationsData.conversations);
|
|
305
|
-
|
|
306
|
-
// Check if agent is paused
|
|
307
|
-
const pauseStatus = await this.checkAgentPauseStatus(agentId, projectDir);
|
|
308
|
-
|
|
309
|
-
const restoredAgent = {
|
|
310
|
-
...stateData.state,
|
|
311
|
-
conversations: conversationsData.conversations,
|
|
312
|
-
isPaused: pauseStatus.isPaused,
|
|
313
|
-
pausedUntil: pauseStatus.pausedUntil,
|
|
314
|
-
isRestored: true,
|
|
315
|
-
restoredAt: new Date().toISOString()
|
|
316
|
-
};
|
|
317
|
-
|
|
318
|
-
this.logger.info(`Agent restored: ${agentId}`, {
|
|
319
|
-
name: restoredAgent.name,
|
|
320
|
-
status: restoredAgent.status,
|
|
321
|
-
messageCount: restoredAgent.conversations?.full?.messages?.length || 0
|
|
322
|
-
});
|
|
323
|
-
|
|
324
|
-
return restoredAgent;
|
|
325
|
-
|
|
326
|
-
} catch (error) {
|
|
327
|
-
this.logger.error(`Agent restoration failed: ${agentId}`, error.message);
|
|
328
|
-
throw error;
|
|
329
|
-
}
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
/**
|
|
333
|
-
* Restore async operations
|
|
334
|
-
* @param {string} projectDir - Project directory path
|
|
335
|
-
* @returns {Promise<Array>} Array of active async operations
|
|
336
|
-
*/
|
|
337
|
-
async restoreAsyncOperations(projectDir) {
|
|
338
|
-
const operationsFile = path.join(projectDir, this.stateDirectory, this.stateFiles.asyncOperations);
|
|
339
|
-
|
|
340
|
-
try {
|
|
341
|
-
const data = await this.loadJSON(operationsFile);
|
|
342
|
-
return data.operations || [];
|
|
343
|
-
} catch {
|
|
344
|
-
return [];
|
|
345
|
-
}
|
|
346
|
-
}
|
|
347
|
-
|
|
348
|
-
/**
|
|
349
|
-
* Restore paused agents
|
|
350
|
-
* @param {string} projectDir - Project directory path
|
|
351
|
-
* @returns {Promise<Object>} Paused agents data
|
|
352
|
-
*/
|
|
353
|
-
async restorePausedAgents(projectDir) {
|
|
354
|
-
const pausedFile = path.join(projectDir, this.stateDirectory, this.stateFiles.pausedAgents);
|
|
355
|
-
|
|
356
|
-
try {
|
|
357
|
-
const data = await this.loadJSON(pausedFile);
|
|
358
|
-
const now = Date.now();
|
|
359
|
-
|
|
360
|
-
// Check which agents should be resumed
|
|
361
|
-
const toResume = [];
|
|
362
|
-
for (const [agentId, pauseInfo] of Object.entries(data.pausedAgents || {})) {
|
|
363
|
-
const pausedUntil = new Date(pauseInfo.pausedUntil).getTime();
|
|
364
|
-
|
|
365
|
-
if (now >= pausedUntil) {
|
|
366
|
-
toResume.push(agentId);
|
|
367
|
-
}
|
|
368
|
-
}
|
|
369
|
-
|
|
370
|
-
// Move expired pauses to history
|
|
371
|
-
for (const agentId of toResume) {
|
|
372
|
-
const pauseInfo = data.pausedAgents[agentId];
|
|
373
|
-
delete data.pausedAgents[agentId];
|
|
374
|
-
|
|
375
|
-
data.pauseHistory = data.pauseHistory || [];
|
|
376
|
-
data.pauseHistory.push({
|
|
377
|
-
agentId,
|
|
378
|
-
pausedAt: pauseInfo.pausedAt,
|
|
379
|
-
resumedAt: new Date().toISOString(),
|
|
380
|
-
reason: pauseInfo.reason,
|
|
381
|
-
actualDuration: Math.round((now - new Date(pauseInfo.pausedAt).getTime()) / 1000)
|
|
382
|
-
});
|
|
383
|
-
}
|
|
384
|
-
|
|
385
|
-
// Save updated data
|
|
386
|
-
await this.saveJSON(pausedFile, data);
|
|
387
|
-
|
|
388
|
-
return data;
|
|
389
|
-
|
|
390
|
-
} catch {
|
|
391
|
-
return {
|
|
392
|
-
pausedAgents: {},
|
|
393
|
-
pauseHistory: []
|
|
394
|
-
};
|
|
395
|
-
}
|
|
396
|
-
}
|
|
397
|
-
|
|
398
|
-
/**
|
|
399
|
-
* Restore context references
|
|
400
|
-
* @param {string} projectDir - Project directory path
|
|
401
|
-
* @returns {Promise<Object>} Context references data
|
|
402
|
-
*/
|
|
403
|
-
async restoreContextReferences(projectDir) {
|
|
404
|
-
const contextFile = path.join(projectDir, this.stateDirectory, this.stateFiles.contextReferences);
|
|
405
|
-
|
|
406
|
-
try {
|
|
407
|
-
const data = await this.loadJSON(contextFile);
|
|
408
|
-
|
|
409
|
-
// Validate context references (implementation would validate file existence, etc.)
|
|
410
|
-
const validatedReferences = [];
|
|
411
|
-
for (const reference of data.references || []) {
|
|
412
|
-
// Add validation logic here
|
|
413
|
-
reference.isValid = true; // Placeholder
|
|
414
|
-
reference.lastValidated = new Date().toISOString();
|
|
415
|
-
validatedReferences.push(reference);
|
|
416
|
-
}
|
|
417
|
-
|
|
418
|
-
data.references = validatedReferences;
|
|
419
|
-
await this.saveJSON(contextFile, data);
|
|
420
|
-
|
|
421
|
-
return data;
|
|
422
|
-
|
|
423
|
-
} catch {
|
|
424
|
-
return {
|
|
425
|
-
references: [],
|
|
426
|
-
lastCleanup: new Date().toISOString()
|
|
427
|
-
};
|
|
428
|
-
}
|
|
429
|
-
}
|
|
430
|
-
|
|
431
|
-
/**
|
|
432
|
-
* Save last session data
|
|
433
|
-
* @param {string} projectDir - Project directory path
|
|
434
|
-
* @param {Object} sessionData - Session data to save
|
|
435
|
-
* @returns {Promise<void>}
|
|
436
|
-
*/
|
|
437
|
-
async saveLastSession(projectDir, sessionData) {
|
|
438
|
-
const sessionFile = path.join(projectDir, this.stateDirectory, this.stateFiles.lastSession);
|
|
439
|
-
|
|
440
|
-
const data = {
|
|
441
|
-
...sessionData,
|
|
442
|
-
savedAt: new Date().toISOString(),
|
|
443
|
-
projectDir
|
|
444
|
-
};
|
|
445
|
-
|
|
446
|
-
await this.saveJSON(sessionFile, data);
|
|
447
|
-
}
|
|
448
|
-
|
|
449
|
-
/**
|
|
450
|
-
* Load last session data
|
|
451
|
-
* @param {string} projectDir - Project directory path
|
|
452
|
-
* @returns {Promise<Object>} Last session data
|
|
453
|
-
*/
|
|
454
|
-
async loadLastSession(projectDir) {
|
|
455
|
-
const sessionFile = path.join(projectDir, this.stateDirectory, this.stateFiles.lastSession);
|
|
456
|
-
|
|
457
|
-
try {
|
|
458
|
-
return await this.loadJSON(sessionFile);
|
|
459
|
-
} catch {
|
|
460
|
-
return null;
|
|
461
|
-
}
|
|
462
|
-
}
|
|
463
|
-
|
|
464
|
-
/**
|
|
465
|
-
* Save paused agent data
|
|
466
|
-
* @param {string} projectDir - Project directory path
|
|
467
|
-
* @param {string} agentId - Agent identifier
|
|
468
|
-
* @param {Object} pauseData - Pause information
|
|
469
|
-
* @returns {Promise<void>}
|
|
470
|
-
*/
|
|
471
|
-
async savePausedAgent(projectDir, agentId, pauseData) {
|
|
472
|
-
const pausedFile = path.join(projectDir, this.stateDirectory, this.stateFiles.pausedAgents);
|
|
473
|
-
|
|
474
|
-
let data;
|
|
475
|
-
try {
|
|
476
|
-
data = await this.loadJSON(pausedFile);
|
|
477
|
-
} catch {
|
|
478
|
-
data = { pausedAgents: {}, pauseHistory: [] };
|
|
479
|
-
}
|
|
480
|
-
|
|
481
|
-
data.pausedAgents[agentId] = pauseData;
|
|
482
|
-
await this.saveJSON(pausedFile, data);
|
|
483
|
-
}
|
|
484
|
-
|
|
485
|
-
/**
|
|
486
|
-
* Remove paused agent data
|
|
487
|
-
* @param {string} projectDir - Project directory path
|
|
488
|
-
* @param {string} agentId - Agent identifier
|
|
489
|
-
* @returns {Promise<void>}
|
|
490
|
-
*/
|
|
491
|
-
async removePausedAgent(projectDir, agentId) {
|
|
492
|
-
const pausedFile = path.join(projectDir, this.stateDirectory, this.stateFiles.pausedAgents);
|
|
493
|
-
|
|
494
|
-
try {
|
|
495
|
-
const data = await this.loadJSON(pausedFile);
|
|
496
|
-
delete data.pausedAgents[agentId];
|
|
497
|
-
await this.saveJSON(pausedFile, data);
|
|
498
|
-
} catch {
|
|
499
|
-
// File doesn't exist, nothing to remove
|
|
500
|
-
}
|
|
501
|
-
}
|
|
502
|
-
|
|
503
|
-
/**
|
|
504
|
-
* Check agent pause status
|
|
505
|
-
* @param {string} agentId - Agent identifier
|
|
506
|
-
* @param {string} projectDir - Project directory path
|
|
507
|
-
* @returns {Promise<Object>} Pause status
|
|
508
|
-
*/
|
|
509
|
-
async checkAgentPauseStatus(agentId, projectDir) {
|
|
510
|
-
const pausedFile = path.join(projectDir, this.stateDirectory, this.stateFiles.pausedAgents);
|
|
511
|
-
|
|
512
|
-
try {
|
|
513
|
-
const data = await this.loadJSON(pausedFile);
|
|
514
|
-
const pauseInfo = data.pausedAgents[agentId];
|
|
515
|
-
|
|
516
|
-
if (!pauseInfo) {
|
|
517
|
-
return { isPaused: false, pausedUntil: null };
|
|
518
|
-
}
|
|
519
|
-
|
|
520
|
-
const now = Date.now();
|
|
521
|
-
const pausedUntil = new Date(pauseInfo.pausedUntil).getTime();
|
|
522
|
-
|
|
523
|
-
return {
|
|
524
|
-
isPaused: now < pausedUntil,
|
|
525
|
-
pausedUntil: pauseInfo.pausedUntil,
|
|
526
|
-
reason: pauseInfo.reason
|
|
527
|
-
};
|
|
528
|
-
|
|
529
|
-
} catch {
|
|
530
|
-
return { isPaused: false, pausedUntil: null };
|
|
531
|
-
}
|
|
532
|
-
}
|
|
533
|
-
|
|
534
|
-
/**
|
|
535
|
-
* Validate model conversations integrity
|
|
536
|
-
* @param {Object} conversations - Conversations object
|
|
537
|
-
* @returns {Promise<void>}
|
|
538
|
-
*/
|
|
539
|
-
async validateModelConversations(conversations) {
|
|
540
|
-
if (!conversations || !conversations.full) {
|
|
541
|
-
throw new Error('Invalid conversations structure - missing full conversation');
|
|
542
|
-
}
|
|
543
|
-
|
|
544
|
-
const fullMessages = conversations.full.messages || [];
|
|
545
|
-
const fullLastUpdated = new Date(conversations.full.lastUpdated);
|
|
546
|
-
|
|
547
|
-
// Validate each model conversation against full conversation
|
|
548
|
-
for (const [modelName, modelConv] of Object.entries(conversations)) {
|
|
549
|
-
if (modelName === 'full') continue;
|
|
550
|
-
|
|
551
|
-
if (!modelConv.messages) {
|
|
552
|
-
this.logger.warn(`Model conversation ${modelName} missing messages array`);
|
|
553
|
-
continue;
|
|
554
|
-
}
|
|
555
|
-
|
|
556
|
-
const modelLastUpdated = new Date(modelConv.lastUpdated);
|
|
557
|
-
|
|
558
|
-
if (fullLastUpdated > modelLastUpdated) {
|
|
559
|
-
this.logger.warn(`Model conversation ${modelName} is outdated, will sync on next use`);
|
|
560
|
-
modelConv.needsSync = true;
|
|
561
|
-
}
|
|
562
|
-
}
|
|
563
|
-
}
|
|
564
|
-
|
|
565
|
-
/**
|
|
566
|
-
* Save JSON data to file
|
|
567
|
-
* @private
|
|
568
|
-
*/
|
|
569
|
-
async saveJSON(filePath, data) {
|
|
570
|
-
const dir = path.dirname(filePath);
|
|
571
|
-
await fs.mkdir(dir, { recursive: true });
|
|
572
|
-
|
|
573
|
-
const jsonData = JSON.stringify(data, null, 2);
|
|
574
|
-
await fs.writeFile(filePath, jsonData, 'utf8');
|
|
575
|
-
}
|
|
576
|
-
|
|
577
|
-
/**
|
|
578
|
-
* Load JSON data from file
|
|
579
|
-
* @private
|
|
580
|
-
*/
|
|
581
|
-
async loadJSON(filePath) {
|
|
582
|
-
const data = await fs.readFile(filePath, 'utf8');
|
|
583
|
-
return JSON.parse(data);
|
|
584
|
-
}
|
|
585
|
-
|
|
586
|
-
/**
|
|
587
|
-
* Delete agent state from storage
|
|
588
|
-
* @param {string} agentId - Agent identifier
|
|
589
|
-
* @param {string} projectDir - Project directory path
|
|
590
|
-
* @returns {Promise<void>}
|
|
591
|
-
*/
|
|
592
|
-
async deleteAgentState(agentId, projectDir = process.cwd()) {
|
|
593
|
-
const stateDir = path.join(projectDir, this.stateDirectory);
|
|
594
|
-
const agentStateFile = path.join(stateDir, 'agents', `agent-${agentId}-state.json`);
|
|
595
|
-
const agentConversationsFile = path.join(stateDir, 'agents', `agent-${agentId}-conversations.json`);
|
|
596
|
-
|
|
597
|
-
try {
|
|
598
|
-
// Delete agent state file
|
|
599
|
-
try {
|
|
600
|
-
await fs.unlink(agentStateFile);
|
|
601
|
-
this.logger.debug(`Deleted agent state file: ${agentId}`);
|
|
602
|
-
} catch (error) {
|
|
603
|
-
if (error.code !== 'ENOENT') {
|
|
604
|
-
this.logger.warn(`Failed to delete agent state file: ${error.message}`, { agentId });
|
|
605
|
-
}
|
|
606
|
-
}
|
|
607
|
-
|
|
608
|
-
// Delete agent conversations file
|
|
609
|
-
try {
|
|
610
|
-
await fs.unlink(agentConversationsFile);
|
|
611
|
-
this.logger.debug(`Deleted agent conversations file: ${agentId}`);
|
|
612
|
-
} catch (error) {
|
|
613
|
-
if (error.code !== 'ENOENT') {
|
|
614
|
-
this.logger.warn(`Failed to delete agent conversations file: ${error.message}`, { agentId });
|
|
615
|
-
}
|
|
616
|
-
}
|
|
617
|
-
|
|
618
|
-
// Remove from agent index
|
|
619
|
-
await this.removeFromAgentIndex(agentId, projectDir);
|
|
620
|
-
|
|
621
|
-
this.logger.info(`Agent state deleted: ${agentId}`);
|
|
622
|
-
|
|
623
|
-
} catch (error) {
|
|
624
|
-
this.logger.error(`Failed to delete agent state: ${error.message}`, {
|
|
625
|
-
agentId,
|
|
626
|
-
error: error.stack
|
|
627
|
-
});
|
|
628
|
-
throw error;
|
|
629
|
-
}
|
|
630
|
-
}
|
|
631
|
-
|
|
632
|
-
/**
|
|
633
|
-
* Remove agent from agent index
|
|
634
|
-
* @param {string} agentId - Agent identifier
|
|
635
|
-
* @param {string} projectDir - Project directory path
|
|
636
|
-
* @returns {Promise<void>}
|
|
637
|
-
*/
|
|
638
|
-
async removeFromAgentIndex(agentId, projectDir) {
|
|
639
|
-
const indexFile = path.join(projectDir, this.stateDirectory, this.stateFiles.agentIndex);
|
|
640
|
-
|
|
641
|
-
try {
|
|
642
|
-
const agentIndex = await this.loadJSON(indexFile);
|
|
643
|
-
delete agentIndex[agentId];
|
|
644
|
-
await this.saveJSON(indexFile, agentIndex);
|
|
645
|
-
this.logger.debug(`Removed agent from index: ${agentId}`);
|
|
646
|
-
} catch (error) {
|
|
647
|
-
// If index doesn't exist or can't be updated, log but don't throw
|
|
648
|
-
this.logger.warn(`Failed to remove agent from index: ${error.message}`, { agentId });
|
|
649
|
-
}
|
|
650
|
-
}
|
|
651
|
-
|
|
652
|
-
/**
|
|
653
|
-
* Check if state directory exists
|
|
654
|
-
* @param {string} projectDir - Project directory path
|
|
655
|
-
* @returns {Promise<boolean>} True if state directory exists
|
|
656
|
-
*/
|
|
657
|
-
async stateDirectoryExists(projectDir) {
|
|
658
|
-
const stateDir = path.join(projectDir, this.stateDirectory);
|
|
659
|
-
|
|
660
|
-
try {
|
|
661
|
-
const stats = await fs.stat(stateDir);
|
|
662
|
-
return stats.isDirectory();
|
|
663
|
-
} catch {
|
|
664
|
-
return false;
|
|
665
|
-
}
|
|
666
|
-
}
|
|
667
|
-
|
|
668
|
-
/**
|
|
669
|
-
* Clean up old state files
|
|
670
|
-
* @param {string} projectDir - Project directory path
|
|
671
|
-
* @param {number} maxAge - Maximum age in days
|
|
672
|
-
* @returns {Promise<void>}
|
|
673
|
-
*/
|
|
674
|
-
async cleanupOldState(projectDir, maxAge = 30) {
|
|
675
|
-
const stateDir = path.join(projectDir, this.stateDirectory);
|
|
676
|
-
const cutoffDate = Date.now() - (maxAge * 24 * 60 * 60 * 1000);
|
|
677
|
-
|
|
678
|
-
try {
|
|
679
|
-
const agentsDir = path.join(stateDir, 'agents');
|
|
680
|
-
const files = await fs.readdir(agentsDir);
|
|
681
|
-
|
|
682
|
-
for (const file of files) {
|
|
683
|
-
const filePath = path.join(agentsDir, file);
|
|
684
|
-
const stats = await fs.stat(filePath);
|
|
685
|
-
|
|
686
|
-
if (stats.mtime.getTime() < cutoffDate) {
|
|
687
|
-
await fs.unlink(filePath);
|
|
688
|
-
this.logger.info(`Cleaned up old state file: ${file}`);
|
|
689
|
-
}
|
|
690
|
-
}
|
|
691
|
-
|
|
692
|
-
} catch (error) {
|
|
693
|
-
this.logger.warn(`State cleanup failed: ${error.message}`);
|
|
694
|
-
}
|
|
695
|
-
}
|
|
696
|
-
|
|
697
|
-
/**
|
|
698
|
-
* Get all available agents (active + archived) from filesystem
|
|
699
|
-
* @param {string} projectDir - Project directory path
|
|
700
|
-
* @param {Object} agentPool - Agent pool instance to check active agents
|
|
701
|
-
* @returns {Promise<Array>} List of all agents with metadata
|
|
702
|
-
*/
|
|
703
|
-
async getAllAvailableAgents(projectDir, agentPool) {
|
|
704
|
-
try {
|
|
705
|
-
const agentIndex = await this.loadAgentIndex(projectDir);
|
|
706
|
-
const activeAgentIds = agentPool ? (await agentPool.getAllAgents()).map(a => a.id) : [];
|
|
707
|
-
|
|
708
|
-
const agents = [];
|
|
709
|
-
for (const [agentId, info] of Object.entries(agentIndex)) {
|
|
710
|
-
// Skip invalid or undefined entries
|
|
711
|
-
if (!info || !info.name) {
|
|
712
|
-
continue;
|
|
713
|
-
}
|
|
714
|
-
|
|
715
|
-
agents.push({
|
|
716
|
-
agentId,
|
|
717
|
-
name: info.name,
|
|
718
|
-
type: info.type,
|
|
719
|
-
model: info.model,
|
|
720
|
-
lastActivity: info.lastActivity,
|
|
721
|
-
status: info.status,
|
|
722
|
-
stateFile: info.stateFile,
|
|
723
|
-
conversationsFile: info.conversationsFile,
|
|
724
|
-
isLoaded: activeAgentIds.includes(agentId),
|
|
725
|
-
canImport: !activeAgentIds.includes(agentId)
|
|
726
|
-
});
|
|
727
|
-
}
|
|
728
|
-
|
|
729
|
-
// Sort by last activity (most recent first)
|
|
730
|
-
agents.sort((a, b) => {
|
|
731
|
-
const dateA = a.lastActivity ? new Date(a.lastActivity) : new Date(0);
|
|
732
|
-
const dateB = b.lastActivity ? new Date(b.lastActivity) : new Date(0);
|
|
733
|
-
return dateB - dateA;
|
|
734
|
-
});
|
|
735
|
-
|
|
736
|
-
this.logger.info(`Found ${agents.length} available agents (${agents.filter(a => a.isLoaded).length} active, ${agents.filter(a => !a.isLoaded).length} archived)`);
|
|
737
|
-
|
|
738
|
-
return agents;
|
|
739
|
-
} catch (error) {
|
|
740
|
-
this.logger.error(`Failed to get available agents: ${error.message}`);
|
|
741
|
-
throw error;
|
|
742
|
-
}
|
|
743
|
-
}
|
|
744
|
-
|
|
745
|
-
/**
|
|
746
|
-
* Get agent metadata without full restoration (lightweight preview)
|
|
747
|
-
* @param {string} agentId - Agent ID
|
|
748
|
-
* @param {string} projectDir - Project directory path
|
|
749
|
-
* @returns {Promise<Object>} Agent metadata for preview
|
|
750
|
-
*/
|
|
751
|
-
async getAgentMetadata(agentId, projectDir) {
|
|
752
|
-
try {
|
|
753
|
-
// Load agent index
|
|
754
|
-
const agentIndex = await this.loadAgentIndex(projectDir);
|
|
755
|
-
const agentInfo = agentIndex[agentId];
|
|
756
|
-
|
|
757
|
-
if (!agentInfo) {
|
|
758
|
-
throw new Error(`Agent ${agentId} not found in index`);
|
|
759
|
-
}
|
|
760
|
-
|
|
761
|
-
// Load just the state file (lightweight)
|
|
762
|
-
const stateDir = path.join(projectDir, this.stateDirectory);
|
|
763
|
-
const stateFile = path.join(stateDir, agentInfo.stateFile);
|
|
764
|
-
const conversationsFile = path.join(stateDir, agentInfo.conversationsFile);
|
|
765
|
-
|
|
766
|
-
// Check if files exist
|
|
767
|
-
const stateExists = await fs.access(stateFile).then(() => true).catch(() => false);
|
|
768
|
-
const conversationsExist = await fs.access(conversationsFile).then(() => true).catch(() => false);
|
|
769
|
-
|
|
770
|
-
if (!stateExists) {
|
|
771
|
-
throw new Error(`State file not found for agent ${agentId}`);
|
|
772
|
-
}
|
|
773
|
-
|
|
774
|
-
// Load state
|
|
775
|
-
const stateData = await this.loadJSON(stateFile);
|
|
776
|
-
const state = stateData.state || {};
|
|
777
|
-
|
|
778
|
-
// Load conversation count without loading full messages (for performance)
|
|
779
|
-
let messageCount = 0;
|
|
780
|
-
let lastMessage = null;
|
|
781
|
-
if (conversationsExist) {
|
|
782
|
-
try {
|
|
783
|
-
const conversations = await this.loadJSON(conversationsFile);
|
|
784
|
-
messageCount = Array.isArray(conversations) ? conversations.length : 0;
|
|
785
|
-
|
|
786
|
-
// Get last message for preview
|
|
787
|
-
if (messageCount > 0) {
|
|
788
|
-
const lastMsg = conversations[conversations.length - 1];
|
|
789
|
-
lastMessage = lastMsg?.content?.substring(0, 100) || null;
|
|
790
|
-
}
|
|
791
|
-
} catch (error) {
|
|
792
|
-
this.logger.warn(`Failed to load conversations for ${agentId}: ${error.message}`);
|
|
793
|
-
}
|
|
794
|
-
}
|
|
795
|
-
|
|
796
|
-
const metadata = {
|
|
797
|
-
agentId,
|
|
798
|
-
name: agentInfo.name || state.name,
|
|
799
|
-
model: agentInfo.model || state.preferredModel || state.currentModel,
|
|
800
|
-
lastActivity: agentInfo.lastActivity,
|
|
801
|
-
status: agentInfo.status,
|
|
802
|
-
capabilities: state.capabilities || [],
|
|
803
|
-
messageCount,
|
|
804
|
-
lastMessage,
|
|
805
|
-
taskCount: state.taskList?.tasks?.length || 0,
|
|
806
|
-
createdAt: state.createdAt,
|
|
807
|
-
workingDirectory: state.directoryAccess?.workingDirectory,
|
|
808
|
-
mode: state.mode,
|
|
809
|
-
systemPrompt: state.originalSystemPrompt
|
|
810
|
-
};
|
|
811
|
-
|
|
812
|
-
this.logger.info(`Loaded metadata for agent ${agentId}: ${metadata.messageCount} messages, ${metadata.taskCount} tasks`);
|
|
813
|
-
|
|
814
|
-
return metadata;
|
|
815
|
-
} catch (error) {
|
|
816
|
-
this.logger.error(`Failed to get agent metadata for ${agentId}: ${error.message}`);
|
|
817
|
-
throw error;
|
|
818
|
-
}
|
|
819
|
-
}
|
|
820
|
-
|
|
821
|
-
/**
|
|
822
|
-
* Import archived agent from filesystem and add to agent pool
|
|
823
|
-
* @param {string} agentId - Agent ID to import
|
|
824
|
-
* @param {string} projectDir - Project directory path
|
|
825
|
-
* @param {Object} agentPool - Agent pool instance
|
|
826
|
-
* @returns {Promise<Object>} Imported agent object
|
|
827
|
-
*/
|
|
828
|
-
async importArchivedAgent(agentId, projectDir, agentPool) {
|
|
829
|
-
try {
|
|
830
|
-
// Validate agent ID format for security
|
|
831
|
-
const AGENT_ID_REGEX = /^agent-[a-z0-9-]+-\d+$/;
|
|
832
|
-
if (!AGENT_ID_REGEX.test(agentId)) {
|
|
833
|
-
throw new Error('Invalid agent ID format');
|
|
834
|
-
}
|
|
835
|
-
|
|
836
|
-
// Check if already loaded in agent pool
|
|
837
|
-
if (agentPool && await agentPool.getAgent(agentId)) {
|
|
838
|
-
throw new Error(`Agent ${agentId} is already loaded. Use switchAgent() instead.`);
|
|
839
|
-
}
|
|
840
|
-
|
|
841
|
-
// Load from agent index
|
|
842
|
-
const agentIndex = await this.loadAgentIndex(projectDir);
|
|
843
|
-
const agentInfo = agentIndex[agentId];
|
|
844
|
-
|
|
845
|
-
if (!agentInfo) {
|
|
846
|
-
throw new Error(`Agent ${agentId} not found in index`);
|
|
847
|
-
}
|
|
848
|
-
|
|
849
|
-
this.logger.info(`Importing archived agent: ${agentId} (${agentInfo.name})`);
|
|
850
|
-
|
|
851
|
-
// Restore agent using existing restore logic
|
|
852
|
-
const agent = await this.restoreAgent(agentId, agentInfo, projectDir);
|
|
853
|
-
|
|
854
|
-
// Update agent's last activity
|
|
855
|
-
agent.lastActivity = new Date().toISOString();
|
|
856
|
-
|
|
857
|
-
// Add to agent pool if provided
|
|
858
|
-
if (agentPool) {
|
|
859
|
-
agentPool.agents.set(agent.id, agent);
|
|
860
|
-
agentPool._updateAgentDirectory(agent);
|
|
861
|
-
this.logger.info(`Agent ${agentId} added to agent pool`);
|
|
862
|
-
}
|
|
863
|
-
|
|
864
|
-
// Update agent index with new last activity
|
|
865
|
-
await this.updateAgentIndex(agent, projectDir);
|
|
866
|
-
|
|
867
|
-
this.logger.info(`Successfully imported agent ${agentId}: ${agent.name}`);
|
|
868
|
-
|
|
869
|
-
return agent;
|
|
870
|
-
} catch (error) {
|
|
871
|
-
this.logger.error(`Failed to import agent ${agentId}: ${error.message}`);
|
|
872
|
-
throw error;
|
|
873
|
-
}
|
|
874
|
-
}
|
|
875
|
-
}
|
|
876
|
-
|
|
877
|
-
export default StateManager;
|
|
1
|
+
const a0_0x198d64=a0_0x6b12;(function(_0x2f1795,_0x278afe){const _0x5b2b28=a0_0x6b12,_0x43b7f5=_0x2f1795();while(!![]){try{const _0x3c4a34=parseInt(_0x5b2b28(0x182))/0x1*(parseInt(_0x5b2b28(0x14b))/0x2)+parseInt(_0x5b2b28(0x11f))/0x3*(parseInt(_0x5b2b28(0x14c))/0x4)+parseInt(_0x5b2b28(0x12b))/0x5*(-parseInt(_0x5b2b28(0x177))/0x6)+parseInt(_0x5b2b28(0x124))/0x7+parseInt(_0x5b2b28(0x128))/0x8+parseInt(_0x5b2b28(0x184))/0x9+parseInt(_0x5b2b28(0x175))/0xa*(-parseInt(_0x5b2b28(0x176))/0xb);if(_0x3c4a34===_0x278afe)break;else _0x43b7f5['push'](_0x43b7f5['shift']());}catch(_0x38cb4a){_0x43b7f5['push'](_0x43b7f5['shift']());}}}(a0_0x2c60,0x4be2d));import{promises as a0_0x4cb03a}from'fs';import a0_0x4a37c3 from'path';class StateManager{constructor(_0x3b9a57,_0x2f4e7e){const _0x186883=a0_0x6b12;this[_0x186883(0x17a)]=_0x3b9a57,this[_0x186883(0x15d)]=_0x2f4e7e,this['stateDirectory']=_0x3b9a57[_0x186883(0x126)]?.[_0x186883(0x15e)]||_0x186883(0x164),this[_0x186883(0x17e)]=_0x186883(0x136),this['stateFiles']={'projectState':'project-state.json','agentIndex':'agent-index.json','conversationIndex':'conversation-index.json','lastSession':'last-session.json','contextReferences':_0x186883(0x17c),'asyncOperations':'operations/async-operations.json','pausedAgents':'operations/paused-agents.json','toolHistory':'operations/tool-history.json','modelRouterCache':'models/model-router-cache.json','errorRecoveryLog':_0x186883(0x188)};}async[a0_0x198d64(0x144)](_0x3e8652){const _0x411c3c=a0_0x198d64,_0x492cc5=a0_0x4a37c3[_0x411c3c(0x183)](_0x3e8652,this[_0x411c3c(0x15e)]);try{await a0_0x4cb03a[_0x411c3c(0x123)](_0x492cc5,{'recursive':!![]}),await a0_0x4cb03a['mkdir'](a0_0x4a37c3[_0x411c3c(0x183)](_0x492cc5,_0x411c3c(0x11b)),{'recursive':!![]}),await a0_0x4cb03a[_0x411c3c(0x123)](a0_0x4a37c3['join'](_0x492cc5,'operations'),{'recursive':!![]}),await a0_0x4cb03a[_0x411c3c(0x123)](a0_0x4a37c3['join'](_0x492cc5,'models'),{'recursive':!![]}),this[_0x411c3c(0x15d)][_0x411c3c(0x152)]('State\x20directory\x20initialized:\x20'+_0x492cc5);}catch(_0x3d9e16){this['logger']['error']('Failed\x20to\x20initialize\x20state\x20directory:\x20'+_0x3d9e16['message']);throw _0x3d9e16;}}async[a0_0x198d64(0x159)](_0x3964e5){const _0x5dcc65=a0_0x198d64;try{await this[_0x5dcc65(0x144)](_0x3964e5);const _0x70e443=await this['loadProjectState'](_0x3964e5),_0x967c40=await this[_0x5dcc65(0x139)](_0x3964e5),_0x330b8e=[];for(const [_0x2207af,_0x5e32fe]of Object[_0x5dcc65(0x134)](_0x967c40)){try{const _0x568569=await this['restoreAgent'](_0x2207af,_0x5e32fe,_0x3964e5);_0x330b8e[_0x5dcc65(0x13e)](_0x568569);}catch(_0x3239cc){this[_0x5dcc65(0x15d)]['warn']('Failed\x20to\x20restore\x20agent:\x20'+_0x2207af,_0x3239cc[_0x5dcc65(0x11a)]);}}const _0x13d62a=await this['restoreAsyncOperations'](_0x3964e5),_0x5d4d38=await this[_0x5dcc65(0x156)](_0x3964e5),_0x20a00=await this[_0x5dcc65(0x122)](_0x3964e5),_0x1b2653={'projectState':_0x70e443,'agents':_0x330b8e,'asyncOperations':_0x13d62a,'pausedAgents':_0x5d4d38,'contextReferences':_0x20a00,'resumedSuccessfully':!![],'resumedAt':new Date()['toISOString']()};return await this['saveLastSession'](_0x3964e5,{'resumedAt':new Date()[_0x5dcc65(0x14d)](),'agentCount':_0x330b8e['length'],'operationCount':_0x13d62a['length']}),this['logger']['info']('Project\x20resumed\x20successfully',{'projectDir':_0x3964e5,'agentCount':_0x330b8e[_0x5dcc65(0x137)],'operationCount':_0x13d62a['length']}),_0x1b2653;}catch(_0x2e301e){return this[_0x5dcc65(0x15d)]['error'](_0x5dcc65(0x13b)+_0x2e301e['message'],{'projectDir':_0x3964e5,'error':_0x2e301e[_0x5dcc65(0x131)]}),{'projectState':null,'agents':[],'asyncOperations':[],'pausedAgents':[],'contextReferences':[],'resumedSuccessfully':![],'error':_0x2e301e['message']};}}async[a0_0x198d64(0x151)](_0x30f4e0,_0x36b6c6=process['cwd']()){const _0x282e78=a0_0x198d64,_0x118342=a0_0x4a37c3[_0x282e78(0x183)](_0x36b6c6,this[_0x282e78(0x15e)]),_0x2f7a95=a0_0x4a37c3[_0x282e78(0x183)](_0x118342,'agents','agent-'+_0x30f4e0['id']+_0x282e78(0x11d)),_0x1025fe=a0_0x4a37c3[_0x282e78(0x183)](_0x118342,_0x282e78(0x11b),'agent-'+_0x30f4e0['id']+_0x282e78(0x13f));try{const {conversations:_0x1196bd,..._0x3e3e1b}=_0x30f4e0;await this[_0x282e78(0x15c)](_0x2f7a95,{'version':this['stateVersion'],'agentId':_0x30f4e0['id'],'state':_0x3e3e1b,'lastPersisted':new Date()['toISOString']()}),await this[_0x282e78(0x15c)](_0x1025fe,{'version':this[_0x282e78(0x17e)],'agentId':_0x30f4e0['id'],'conversations':_0x1196bd,'lastPersisted':new Date()['toISOString']()}),await this[_0x282e78(0x12f)](_0x30f4e0,_0x36b6c6),this[_0x282e78(0x15d)]['debug']('Agent\x20state\x20persisted:\x20'+_0x30f4e0['id']);}catch(_0x33178f){this['logger'][_0x282e78(0x192)]('Failed\x20to\x20persist\x20agent\x20state:\x20'+_0x33178f[_0x282e78(0x11a)],{'agentId':_0x30f4e0['id'],'error':_0x33178f['stack']});throw _0x33178f;}}async['getProjectState'](_0x1fe105){const _0x19adf9=a0_0x198d64;return await this[_0x19adf9(0x17d)](_0x1fe105);}async['loadProjectState'](_0xc25717){const _0x2e5f9e=a0_0x198d64,_0x1b3af0=a0_0x4a37c3['join'](_0xc25717,this[_0x2e5f9e(0x15e)],this[_0x2e5f9e(0x16d)][_0x2e5f9e(0x154)]);try{const _0x369f93=await this['loadJSON'](_0x1b3af0);return _0x369f93;}catch(_0x87f7a){const defaultState={'version':this[_0x2e5f9e(0x17e)],'projectDir':_0xc25717,'createdAt':new Date()[_0x2e5f9e(0x14d)](),'lastModified':new Date()[_0x2e5f9e(0x14d)](),'activeAgents':[],'lastActiveSession':null,'configuration':{'defaultModel':this['config'][_0x2e5f9e(0x126)]?.[_0x2e5f9e(0x149)]||_0x2e5f9e(0x17f),'allowedTools':[_0x2e5f9e(0x16a),_0x2e5f9e(0x179),_0x2e5f9e(0x14a)],'budgetLimit':0x64}};return await this['saveProjectState'](_0xc25717,defaultState),defaultState;}}async[a0_0x198d64(0x160)](_0x5d63f2,_0x1c2a02){const _0x3da885=a0_0x198d64,_0x710cf2=a0_0x4a37c3[_0x3da885(0x183)](_0x5d63f2,this['stateDirectory'],this['stateFiles']['projectState']),_0x15d961={..._0x1c2a02,'lastModified':new Date()[_0x3da885(0x14d)]()};await this[_0x3da885(0x15c)](_0x710cf2,_0x15d961);}async[a0_0x198d64(0x139)](_0xd177cf){const _0x224083=a0_0x198d64,_0x22a700=a0_0x4a37c3['join'](_0xd177cf,this['stateDirectory'],this[_0x224083(0x16d)]['agentIndex']);try{return await this[_0x224083(0x191)](_0x22a700);}catch(_0xb69cc7){return{};}}async['updateAgentIndex'](_0x56d7e8,_0x2e3ca7){const _0x45e3f4=a0_0x198d64,_0x3e9bc0=a0_0x4a37c3['join'](_0x2e3ca7,this['stateDirectory'],this[_0x45e3f4(0x16d)][_0x45e3f4(0x185)]);let _0x15f2cd;try{_0x15f2cd=await this['loadJSON'](_0x3e9bc0);}catch{_0x15f2cd={};}_0x15f2cd[_0x56d7e8['id']]={'name':_0x56d7e8[_0x45e3f4(0x178)],'type':_0x56d7e8[_0x45e3f4(0x11c)],'stateFile':'agents/agent-'+_0x56d7e8['id']+_0x45e3f4(0x11d),'conversationsFile':'agents/agent-'+_0x56d7e8['id']+_0x45e3f4(0x13f),'lastActivity':_0x56d7e8['lastActivity'],'model':_0x56d7e8['currentModel'],'status':_0x56d7e8[_0x45e3f4(0x133)]},await this['saveJSON'](_0x3e9bc0,_0x15f2cd);}async[a0_0x198d64(0x167)](_0x5649fc,_0x2451fa,_0x2b9845){const _0x441e49=a0_0x198d64,_0x1dba07=a0_0x4a37c3['join'](_0x2b9845,this[_0x441e49(0x15e)]),_0x265442=a0_0x4a37c3[_0x441e49(0x183)](_0x1dba07,_0x2451fa[_0x441e49(0x14f)]),_0x1dcd63=a0_0x4a37c3['join'](_0x1dba07,_0x2451fa[_0x441e49(0x125)]);try{const _0x141504=await this['loadJSON'](_0x265442),_0x1bea60=await this[_0x441e49(0x191)](_0x1dcd63);await this['validateModelConversations'](_0x1bea60[_0x441e49(0x186)]);const _0x1edca9=await this['checkAgentPauseStatus'](_0x5649fc,_0x2b9845),_0x3150fc={..._0x141504['state'],'conversations':_0x1bea60['conversations'],'isPaused':_0x1edca9['isPaused'],'pausedUntil':_0x1edca9[_0x441e49(0x166)],'isRestored':!![],'restoredAt':new Date()[_0x441e49(0x14d)]()};return this['logger']['info']('Agent\x20restored:\x20'+_0x5649fc,{'name':_0x3150fc[_0x441e49(0x178)],'status':_0x3150fc[_0x441e49(0x133)],'messageCount':_0x3150fc[_0x441e49(0x186)]?.[_0x441e49(0x161)]?.[_0x441e49(0x11e)]?.[_0x441e49(0x137)]||0x0}),_0x3150fc;}catch(_0x4a6258){this['logger']['error'](_0x441e49(0x129)+_0x5649fc,_0x4a6258[_0x441e49(0x11a)]);throw _0x4a6258;}}async[a0_0x198d64(0x18f)](_0x273ac4){const _0x1e8adb=a0_0x198d64,_0x3e170c=a0_0x4a37c3[_0x1e8adb(0x183)](_0x273ac4,this[_0x1e8adb(0x15e)],this[_0x1e8adb(0x16d)]['asyncOperations']);try{const _0x1830d3=await this[_0x1e8adb(0x191)](_0x3e170c);return _0x1830d3[_0x1e8adb(0x15a)]||[];}catch{return[];}}async['restorePausedAgents'](_0xfa3e78){const _0x1f6f52=a0_0x198d64,_0x48f2ab=a0_0x4a37c3['join'](_0xfa3e78,this['stateDirectory'],this['stateFiles'][_0x1f6f52(0x169)]);try{const _0xc77f80=await this['loadJSON'](_0x48f2ab),_0x3808d4=Date[_0x1f6f52(0x140)](),_0x57c381=[];for(const [_0x419b6a,_0x41e5aa]of Object[_0x1f6f52(0x134)](_0xc77f80[_0x1f6f52(0x169)]||{})){const _0x468343=new Date(_0x41e5aa[_0x1f6f52(0x166)])['getTime']();_0x3808d4>=_0x468343&&_0x57c381['push'](_0x419b6a);}for(const _0x2eb64c of _0x57c381){const _0x47b0a5=_0xc77f80[_0x1f6f52(0x169)][_0x2eb64c];delete _0xc77f80['pausedAgents'][_0x2eb64c],_0xc77f80[_0x1f6f52(0x15f)]=_0xc77f80['pauseHistory']||[],_0xc77f80[_0x1f6f52(0x15f)][_0x1f6f52(0x13e)]({'agentId':_0x2eb64c,'pausedAt':_0x47b0a5['pausedAt'],'resumedAt':new Date()['toISOString'](),'reason':_0x47b0a5['reason'],'actualDuration':Math[_0x1f6f52(0x193)]((_0x3808d4-new Date(_0x47b0a5['pausedAt'])[_0x1f6f52(0x16c)]())/0x3e8)});}return await this['saveJSON'](_0x48f2ab,_0xc77f80),_0xc77f80;}catch{return{'pausedAgents':{},'pauseHistory':[]};}}async['restoreContextReferences'](_0x52e115){const _0x282b77=a0_0x198d64,_0x46d365=a0_0x4a37c3[_0x282b77(0x183)](_0x52e115,this[_0x282b77(0x15e)],this['stateFiles']['contextReferences']);try{const _0x6d49cc=await this[_0x282b77(0x191)](_0x46d365),_0x19ae6b=[];for(const _0x4ab75a of _0x6d49cc['references']||[]){_0x4ab75a[_0x282b77(0x180)]=!![],_0x4ab75a['lastValidated']=new Date()['toISOString'](),_0x19ae6b[_0x282b77(0x13e)](_0x4ab75a);}return _0x6d49cc['references']=_0x19ae6b,await this[_0x282b77(0x15c)](_0x46d365,_0x6d49cc),_0x6d49cc;}catch{return{'references':[],'lastCleanup':new Date()['toISOString']()};}}async['saveLastSession'](_0x3225bd,_0x2ce22e){const _0x549ee0=a0_0x198d64,_0xc2952=a0_0x4a37c3[_0x549ee0(0x183)](_0x3225bd,this[_0x549ee0(0x15e)],this['stateFiles']['lastSession']),_0x21ab18={..._0x2ce22e,'savedAt':new Date()[_0x549ee0(0x14d)](),'projectDir':_0x3225bd};await this['saveJSON'](_0xc2952,_0x21ab18);}async['loadLastSession'](_0x87b643){const _0x2deb7f=a0_0x198d64,_0x316632=a0_0x4a37c3[_0x2deb7f(0x183)](_0x87b643,this[_0x2deb7f(0x15e)],this['stateFiles'][_0x2deb7f(0x153)]);try{return await this[_0x2deb7f(0x191)](_0x316632);}catch{return null;}}async['savePausedAgent'](_0x4204bf,_0x16b9d3,_0x32d874){const _0x183c31=a0_0x198d64,_0x4222a6=a0_0x4a37c3['join'](_0x4204bf,this['stateDirectory'],this[_0x183c31(0x16d)]['pausedAgents']);let _0x2d7ad3;try{_0x2d7ad3=await this['loadJSON'](_0x4222a6);}catch{_0x2d7ad3={'pausedAgents':{},'pauseHistory':[]};}_0x2d7ad3['pausedAgents'][_0x16b9d3]=_0x32d874,await this['saveJSON'](_0x4222a6,_0x2d7ad3);}async[a0_0x198d64(0x146)](_0x3ec684,_0x8806fd){const _0x572f83=a0_0x198d64,_0xa8f5a=a0_0x4a37c3[_0x572f83(0x183)](_0x3ec684,this['stateDirectory'],this[_0x572f83(0x16d)]['pausedAgents']);try{const _0x38546f=await this[_0x572f83(0x191)](_0xa8f5a);delete _0x38546f['pausedAgents'][_0x8806fd],await this[_0x572f83(0x15c)](_0xa8f5a,_0x38546f);}catch{}}async['checkAgentPauseStatus'](_0x18fb47,_0x3d58f9){const _0x2983a2=a0_0x198d64,_0x3a9738=a0_0x4a37c3[_0x2983a2(0x183)](_0x3d58f9,this['stateDirectory'],this[_0x2983a2(0x16d)]['pausedAgents']);try{const _0x3998df=await this[_0x2983a2(0x191)](_0x3a9738),_0x4cd1cc=_0x3998df[_0x2983a2(0x169)][_0x18fb47];if(!_0x4cd1cc)return{'isPaused':![],'pausedUntil':null};const _0x194ffd=Date[_0x2983a2(0x140)](),_0x45c1ef=new Date(_0x4cd1cc['pausedUntil'])[_0x2983a2(0x16c)]();return{'isPaused':_0x194ffd<_0x45c1ef,'pausedUntil':_0x4cd1cc[_0x2983a2(0x166)],'reason':_0x4cd1cc['reason']};}catch{return{'isPaused':![],'pausedUntil':null};}}async['validateModelConversations'](_0x1b6b21){const _0x4fdc56=a0_0x198d64;if(!_0x1b6b21||!_0x1b6b21[_0x4fdc56(0x161)])throw new Error(_0x4fdc56(0x16e));const _0xf8b194=_0x1b6b21['full']['messages']||[],_0x4c5bb6=new Date(_0x1b6b21['full'][_0x4fdc56(0x172)]);for(const [_0x35bfa5,_0x29ed84]of Object[_0x4fdc56(0x134)](_0x1b6b21)){if(_0x35bfa5===_0x4fdc56(0x161))continue;if(!_0x29ed84['messages']){this['logger']['warn']('Model\x20conversation\x20'+_0x35bfa5+_0x4fdc56(0x18a));continue;}const _0x10388c=new Date(_0x29ed84[_0x4fdc56(0x172)]);_0x4c5bb6>_0x10388c&&(this[_0x4fdc56(0x15d)][_0x4fdc56(0x189)]('Model\x20conversation\x20'+_0x35bfa5+_0x4fdc56(0x155)),_0x29ed84['needsSync']=!![]);}}async['saveJSON'](_0x20dbb1,_0x128db8){const _0x3f229f=a0_0x198d64,_0x5f30ea=a0_0x4a37c3[_0x3f229f(0x141)](_0x20dbb1);await a0_0x4cb03a['mkdir'](_0x5f30ea,{'recursive':!![]});const _0x2b0679=JSON['stringify'](_0x128db8,null,0x2);await a0_0x4cb03a[_0x3f229f(0x127)](_0x20dbb1,_0x2b0679,_0x3f229f(0x15b));}async[a0_0x198d64(0x191)](_0xa056e){const _0x4a3824=await a0_0x4cb03a['readFile'](_0xa056e,'utf8');return JSON['parse'](_0x4a3824);}async['deleteAgentState'](_0x55e783,_0x26fc6a=process['cwd']()){const _0x254139=a0_0x198d64,_0x476898=a0_0x4a37c3[_0x254139(0x183)](_0x26fc6a,this[_0x254139(0x15e)]),_0x1337e2=a0_0x4a37c3['join'](_0x476898,'agents','agent-'+_0x55e783+'-state.json'),_0x1d6d04=a0_0x4a37c3[_0x254139(0x183)](_0x476898,_0x254139(0x11b),_0x254139(0x16b)+_0x55e783+'-conversations.json');try{try{await a0_0x4cb03a[_0x254139(0x190)](_0x1337e2),this[_0x254139(0x15d)][_0x254139(0x147)]('Deleted\x20agent\x20state\x20file:\x20'+_0x55e783);}catch(_0x4701d3){_0x4701d3['code']!=='ENOENT'&&this[_0x254139(0x15d)]['warn']('Failed\x20to\x20delete\x20agent\x20state\x20file:\x20'+_0x4701d3['message'],{'agentId':_0x55e783});}try{await a0_0x4cb03a[_0x254139(0x190)](_0x1d6d04),this[_0x254139(0x15d)]['debug'](_0x254139(0x119)+_0x55e783);}catch(_0x3d757e){_0x3d757e[_0x254139(0x174)]!=='ENOENT'&&this['logger'][_0x254139(0x189)]('Failed\x20to\x20delete\x20agent\x20conversations\x20file:\x20'+_0x3d757e['message'],{'agentId':_0x55e783});}await this[_0x254139(0x120)](_0x55e783,_0x26fc6a),this[_0x254139(0x15d)]['info'](_0x254139(0x13d)+_0x55e783);}catch(_0x2d11f4){this['logger']['error'](_0x254139(0x142)+_0x2d11f4['message'],{'agentId':_0x55e783,'error':_0x2d11f4['stack']});throw _0x2d11f4;}}async['removeFromAgentIndex'](_0x19a879,_0x169d8f){const _0x135477=a0_0x198d64,_0x5d087e=a0_0x4a37c3[_0x135477(0x183)](_0x169d8f,this[_0x135477(0x15e)],this[_0x135477(0x16d)][_0x135477(0x185)]);try{const _0x4c84cd=await this[_0x135477(0x191)](_0x5d087e);delete _0x4c84cd[_0x19a879],await this[_0x135477(0x15c)](_0x5d087e,_0x4c84cd),this['logger'][_0x135477(0x147)]('Removed\x20agent\x20from\x20index:\x20'+_0x19a879);}catch(_0x5bb70f){this['logger']['warn']('Failed\x20to\x20remove\x20agent\x20from\x20index:\x20'+_0x5bb70f[_0x135477(0x11a)],{'agentId':_0x19a879});}}async[a0_0x198d64(0x132)](_0x1fc696){const _0x4ea0b9=a0_0x198d64,_0x38a932=a0_0x4a37c3[_0x4ea0b9(0x183)](_0x1fc696,this[_0x4ea0b9(0x15e)]);try{const _0x45a033=await a0_0x4cb03a['stat'](_0x38a932);return _0x45a033[_0x4ea0b9(0x18e)]();}catch{return![];}}async[a0_0x198d64(0x187)](_0x158c40,_0x1e4be3=0x1e){const _0x74c67c=a0_0x198d64,_0x30c2c4=a0_0x4a37c3['join'](_0x158c40,this['stateDirectory']),_0x4fc98f=Date[_0x74c67c(0x140)]()-_0x1e4be3*0x18*0x3c*0x3c*0x3e8;try{const _0x1b568f=a0_0x4a37c3[_0x74c67c(0x183)](_0x30c2c4,_0x74c67c(0x11b)),_0x1f174e=await a0_0x4cb03a[_0x74c67c(0x12a)](_0x1b568f);for(const _0x5893e6 of _0x1f174e){const _0x4d6db9=a0_0x4a37c3[_0x74c67c(0x183)](_0x1b568f,_0x5893e6),_0x3dc345=await a0_0x4cb03a['stat'](_0x4d6db9);_0x3dc345['mtime']['getTime']()<_0x4fc98f&&(await a0_0x4cb03a[_0x74c67c(0x190)](_0x4d6db9),this['logger']['info']('Cleaned\x20up\x20old\x20state\x20file:\x20'+_0x5893e6));}}catch(_0x4ffcb9){this['logger'][_0x74c67c(0x189)](_0x74c67c(0x138)+_0x4ffcb9[_0x74c67c(0x11a)]);}}async['getAllAvailableAgents'](_0x1898dd,_0x45cfca){const _0x5dd09b=a0_0x198d64;try{const _0x585d4a=await this['loadAgentIndex'](_0x1898dd),_0x2f092c=_0x45cfca?(await _0x45cfca[_0x5dd09b(0x148)]())[_0x5dd09b(0x173)](_0xa85600=>_0xa85600['id']):[],_0x49950a=[];for(const [_0x3103de,_0x24deaf]of Object['entries'](_0x585d4a)){if(!_0x24deaf||!_0x24deaf[_0x5dd09b(0x178)])continue;_0x49950a['push']({'agentId':_0x3103de,'name':_0x24deaf[_0x5dd09b(0x178)],'type':_0x24deaf[_0x5dd09b(0x11c)],'model':_0x24deaf[_0x5dd09b(0x12c)],'lastActivity':_0x24deaf[_0x5dd09b(0x16f)],'status':_0x24deaf['status'],'stateFile':_0x24deaf['stateFile'],'conversationsFile':_0x24deaf['conversationsFile'],'isLoaded':_0x2f092c[_0x5dd09b(0x171)](_0x3103de),'canImport':!_0x2f092c['includes'](_0x3103de)});}return _0x49950a['sort']((_0x164418,_0x1145bd)=>{const _0xdc2331=_0x5dd09b,_0x1d2cd5=_0x164418[_0xdc2331(0x16f)]?new Date(_0x164418[_0xdc2331(0x16f)]):new Date(0x0),_0x2ca7fb=_0x1145bd['lastActivity']?new Date(_0x1145bd[_0xdc2331(0x16f)]):new Date(0x0);return _0x2ca7fb-_0x1d2cd5;}),this['logger']['info'](_0x5dd09b(0x121)+_0x49950a[_0x5dd09b(0x137)]+'\x20available\x20agents\x20('+_0x49950a['filter'](_0x466d44=>_0x466d44[_0x5dd09b(0x18d)])['length']+'\x20active,\x20'+_0x49950a['filter'](_0x2b1991=>!_0x2b1991['isLoaded'])[_0x5dd09b(0x137)]+_0x5dd09b(0x12d)),_0x49950a;}catch(_0x3fd686){this['logger']['error'](_0x5dd09b(0x145)+_0x3fd686['message']);throw _0x3fd686;}}async['getAgentMetadata'](_0x4c8b96,_0x1555ce){const _0xd57b2=a0_0x198d64;try{const _0x1f201a=await this['loadAgentIndex'](_0x1555ce),_0x57211e=_0x1f201a[_0x4c8b96];if(!_0x57211e)throw new Error('Agent\x20'+_0x4c8b96+_0xd57b2(0x181));const _0x2daab3=a0_0x4a37c3['join'](_0x1555ce,this['stateDirectory']),_0x3e4bf5=a0_0x4a37c3['join'](_0x2daab3,_0x57211e[_0xd57b2(0x14f)]),_0x4ecb01=a0_0x4a37c3['join'](_0x2daab3,_0x57211e['conversationsFile']),_0x3844e2=await a0_0x4cb03a['access'](_0x3e4bf5)['then'](()=>!![])[_0xd57b2(0x14e)](()=>![]),_0x435015=await a0_0x4cb03a['access'](_0x4ecb01)[_0xd57b2(0x163)](()=>!![])['catch'](()=>![]);if(!_0x3844e2)throw new Error('State\x20file\x20not\x20found\x20for\x20agent\x20'+_0x4c8b96);const _0x2b8717=await this['loadJSON'](_0x3e4bf5),_0x1c12d3=_0x2b8717['state']||{};let _0x54e828=0x0,_0x3dde51=null;if(_0x435015)try{const _0x82945e=await this[_0xd57b2(0x191)](_0x4ecb01);_0x54e828=Array[_0xd57b2(0x168)](_0x82945e)?_0x82945e[_0xd57b2(0x137)]:0x0;if(_0x54e828>0x0){const _0x288f29=_0x82945e[_0x82945e[_0xd57b2(0x137)]-0x1];_0x3dde51=_0x288f29?.['content']?.[_0xd57b2(0x143)](0x0,0x64)||null;}}catch(_0x1ee024){this['logger'][_0xd57b2(0x189)](_0xd57b2(0x13c)+_0x4c8b96+':\x20'+_0x1ee024['message']);}const _0x2f933e={'agentId':_0x4c8b96,'name':_0x57211e['name']||_0x1c12d3['name'],'model':_0x57211e['model']||_0x1c12d3[_0xd57b2(0x150)]||_0x1c12d3['currentModel'],'lastActivity':_0x57211e[_0xd57b2(0x16f)],'status':_0x57211e[_0xd57b2(0x133)],'capabilities':_0x1c12d3['capabilities']||[],'messageCount':_0x54e828,'lastMessage':_0x3dde51,'taskCount':_0x1c12d3[_0xd57b2(0x157)]?.[_0xd57b2(0x170)]?.['length']||0x0,'createdAt':_0x1c12d3['createdAt'],'workingDirectory':_0x1c12d3['directoryAccess']?.['workingDirectory'],'mode':_0x1c12d3['mode'],'systemPrompt':_0x1c12d3[_0xd57b2(0x18b)]};return this['logger'][_0xd57b2(0x152)]('Loaded\x20metadata\x20for\x20agent\x20'+_0x4c8b96+':\x20'+_0x2f933e[_0xd57b2(0x18c)]+'\x20messages,\x20'+_0x2f933e[_0xd57b2(0x130)]+'\x20tasks'),_0x2f933e;}catch(_0x2af48f){this['logger'][_0xd57b2(0x192)](_0xd57b2(0x135)+_0x4c8b96+':\x20'+_0x2af48f['message']);throw _0x2af48f;}}async[a0_0x198d64(0x12e)](_0x182b98,_0x4ba374,_0x19e96a){const _0x5db030=a0_0x198d64;try{const _0x47d1a9=/^agent-[a-z0-9-]+-\d+$/;if(!_0x47d1a9['test'](_0x182b98))throw new Error(_0x5db030(0x17b));if(_0x19e96a&&await _0x19e96a[_0x5db030(0x165)](_0x182b98))throw new Error(_0x5db030(0x158)+_0x182b98+'\x20is\x20already\x20loaded.\x20Use\x20switchAgent()\x20instead.');const _0x1742f5=await this[_0x5db030(0x139)](_0x4ba374),_0x1a7863=_0x1742f5[_0x182b98];if(!_0x1a7863)throw new Error(_0x5db030(0x158)+_0x182b98+'\x20not\x20found\x20in\x20index');this[_0x5db030(0x15d)][_0x5db030(0x152)]('Importing\x20archived\x20agent:\x20'+_0x182b98+'\x20('+_0x1a7863['name']+')');const _0x32c2ba=await this['restoreAgent'](_0x182b98,_0x1a7863,_0x4ba374);return _0x32c2ba[_0x5db030(0x16f)]=new Date()[_0x5db030(0x14d)](),_0x19e96a&&(_0x19e96a[_0x5db030(0x11b)][_0x5db030(0x162)](_0x32c2ba['id'],_0x32c2ba),_0x19e96a['_updateAgentDirectory'](_0x32c2ba),this[_0x5db030(0x15d)][_0x5db030(0x152)](_0x5db030(0x158)+_0x182b98+_0x5db030(0x13a))),await this[_0x5db030(0x12f)](_0x32c2ba,_0x4ba374),this[_0x5db030(0x15d)]['info']('Successfully\x20imported\x20agent\x20'+_0x182b98+':\x20'+_0x32c2ba[_0x5db030(0x178)]),_0x32c2ba;}catch(_0x59a545){this['logger'][_0x5db030(0x192)]('Failed\x20to\x20import\x20agent\x20'+_0x182b98+':\x20'+_0x59a545['message']);throw _0x59a545;}}}function a0_0x6b12(_0x330494,_0x324395){_0x330494=_0x330494-0x119;const _0x2c6081=a0_0x2c60();let _0x6b12a8=_0x2c6081[_0x330494];if(a0_0x6b12['ZFrNTp']===undefined){var _0x151ed5=function(_0x34b4dc){const _0x46a522='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';let _0x4cb03a='',_0x4a37c3='';for(let _0x3b9a57=0x0,_0x2f4e7e,_0x3e8652,_0x492cc5=0x0;_0x3e8652=_0x34b4dc['charAt'](_0x492cc5++);~_0x3e8652&&(_0x2f4e7e=_0x3b9a57%0x4?_0x2f4e7e*0x40+_0x3e8652:_0x3e8652,_0x3b9a57++%0x4)?_0x4cb03a+=String['fromCharCode'](0xff&_0x2f4e7e>>(-0x2*_0x3b9a57&0x6)):0x0){_0x3e8652=_0x46a522['indexOf'](_0x3e8652);}for(let _0x3d9e16=0x0,_0x3964e5=_0x4cb03a['length'];_0x3d9e16<_0x3964e5;_0x3d9e16++){_0x4a37c3+='%'+('00'+_0x4cb03a['charCodeAt'](_0x3d9e16)['toString'](0x10))['slice'](-0x2);}return decodeURIComponent(_0x4a37c3);};a0_0x6b12['sXTKVA']=_0x151ed5,a0_0x6b12['qdJBAw']={},a0_0x6b12['ZFrNTp']=!![];}const _0x54111c=_0x2c6081[0x0],_0x382b86=_0x330494+_0x54111c,_0x17381f=a0_0x6b12['qdJBAw'][_0x382b86];return!_0x17381f?(_0x6b12a8=a0_0x6b12['sXTKVA'](_0x6b12a8),a0_0x6b12['qdJBAw'][_0x382b86]=_0x6b12a8):_0x6b12a8=_0x17381f,_0x6b12a8;}export default StateManager;function a0_0x2c60(){const _0x4ce371=['zgLYBMfTzq','rMfPBgvKihrVigrLBgv0zsbHz2vUDcbZDgf0ztOG','C3vIC3rYAw5N','Aw5PDgLHBgL6zvn0yxrLrgLYzwn0B3j5','rMfPBgvKihrVigDLDcbHDMfPBgfIBguGywDLBNrZoIa','CMvTB3zLugf1C2vKqwDLBNq','zgvIDwC','z2v0qwXSqwDLBNrZ','zgvMyxvSDe1VzgvS','yNjVD3nLCG','nZa2D1bVCg1r','mtyWnda0EhLhq0rV','Dg9ju09tDhjPBMC','y2f0y2G','C3rHDgvgAwXL','ChjLzMvYCMvKtw9KzwW','CgvYC2LZDefNzw50u3rHDgu','Aw5MBW','BgfZDfnLC3nPB24','ChjVAMvJDfn0yxrL','igLZig91DgrHDgvKlcb3AwXSihn5BMmGB24GBMv4Dcb1C2u','CMvZDg9YzvbHDxnLzefNzw50CW','DgfZA0XPC3q','qwDLBNqG','CMvZDw1LuhjVAMvJDa','B3bLCMf0Aw9UCW','DxrMoa','C2f2zuPtt04','Bg9Nz2vY','C3rHDgveAxjLy3rVCNK','Cgf1C2viAxn0B3j5','C2f2zvbYB2PLy3rtDgf0zq','zNvSBa','C2v0','DgHLBG','lMXVEgLHlxn0yxrL','z2v0qwDLBNq','Cgf1C2vKvw50AwW','CMvZDg9YzufNzw50','AxnbCNjHEq','Cgf1C2vKqwDLBNrZ','DgvYBwLUywW','ywDLBNqT','z2v0vgLTzq','C3rHDgvgAwXLCW','sw52ywXPzcbJB252zxjZyxrPB25Zihn0CNvJDhvYzsaTig1PC3nPBMCGzNvSBcbJB252zxjZyxrPB24','BgfZDefJDgL2Axr5','DgfZA3m','Aw5JBhvKzxm','BgfZDfvWzgf0zwq','BwfW','y29Kzq','mtbLBwzdBgm','odiWmdeYnMnpt3zSvG','nZHRzvjYzNC','BMfTzq','zMLSzxn5C3rLBq','y29UzMLN','sw52ywXPzcbHz2vUDcbjrcbMB3jTyxq','y29UDgv4Dc1YzwzLCMvUy2vZlMPZB24','Bg9HzfbYB2PLy3rtDgf0zq','C3rHDgvwzxjZAw9U','yw50AhjVCgLJlxnVBM5LDa','AxnwywXPza','ig5VDcbMB3vUzcbPBIbPBMrLEa','mtm0n2PZvgP5qG','AM9PBG','nda5nZCWmhnov3fQAq','ywDLBNrjBMrLEa','y29UDMvYC2f0Aw9UCW','y2XLyw51Ce9Szfn0yxrL','Bw9KzwXZl2vYCM9YlxjLy292zxj5lwXVzY5QC29U','D2fYBG','ig1PC3nPBMCGBwvZC2fNzxmGyxjYyxK','B3jPz2LUywXtExn0zw1qCM9TChq','BwvZC2fNzunVDw50','AxnmB2fKzwq','AxneAxjLy3rVCNK','CMvZDg9YzufZEw5Jt3bLCMf0Aw9UCW','Dw5SAw5R','Bg9HzePtt04','zxjYB3i','CM91BMq','rgvSzxrLzcbHz2vUDcbJB252zxjZyxrPB25ZigzPBgu6ia','BwvZC2fNzq','ywDLBNrZ','DhLWzq','lxn0yxrLlMPZB24','BwvZC2fNzxm','m3jZsezvyq','CMvTB3zLrNjVBufNzw50sw5KzxG','rM91BMqG','CMvZDg9YzunVBNrLEhrszwzLCMvUy2vZ','BwTKAxi','mJmZmJi2mg1JvhjsAW','y29UDMvYC2f0Aw9UC0zPBgu','C3LZDgvT','D3jPDgvgAwXL','mJG1nZuYofvSs3zmyq','qwDLBNqGCMvZDg9YyxrPB24GzMfPBgvKoIa','CMvHzgrPCG','mJmYnJGWA3jur2Dw','Bw9KzwW','igfYy2HPDMvKkq','Aw1WB3j0qxjJAgL2zwrbz2vUDa','DxbKyxrLqwDLBNrjBMrLEa','DgfZA0nVDw50','C3rHy2S','C3rHDgveAxjLy3rVCNLfEgLZDhm','C3rHDhvZ','zw50CMLLCW','rMfPBgvKihrVigDLDcbHz2vUDcbTzxrHzgf0ysbMB3iG','ms4WlJa','BgvUz3rO','u3rHDguGy2XLyw51CcbMywLSzwq6ia','Bg9HzefNzw50sw5KzxG','igfKzgvKihrVigfNzw50ihbVB2W','uhjVAMvJDcbYzxn1BwuGzMfPBgvKoIa','rMfPBgvKihrVigXVywqGy29UDMvYC2f0Aw9UCYbMB3iG','qwDLBNqGC3rHDguGzgvSzxrLzdOG','ChvZAa','lwnVBNzLCNnHDgLVBNmUANnVBG','BM93'];a0_0x2c60=function(){return _0x4ce371;};return a0_0x2c60();}
|