@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
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_0x4baeee=a0_0xc826;(function(_0x572787,_0x2b5cf8){const _0x436c09=a0_0xc826,_0x118571=_0x572787();while(!![]){try{const _0x4af581=parseInt(_0x436c09(0x8a))/0x1*(-parseInt(_0x436c09(0xd3))/0x2)+-parseInt(_0x436c09(0xf9))/0x3+-parseInt(_0x436c09(0xba))/0x4+-parseInt(_0x436c09(0x9f))/0x5+-parseInt(_0x436c09(0xed))/0x6+parseInt(_0x436c09(0xce))/0x7*(parseInt(_0x436c09(0x8c))/0x8)+parseInt(_0x436c09(0xc8))/0x9*(parseInt(_0x436c09(0x92))/0xa);if(_0x4af581===_0x2b5cf8)break;else _0x118571['push'](_0x118571['shift']());}catch(_0x1e4f03){_0x118571['push'](_0x118571['shift']());}}}(a0_0x54ea,0xd9388));import{promises as a0_0x8d03f4}from'fs';import a0_0x1280ea from'path';function a0_0x54ea(){const _0x276e7e=['z2v0qwXSqwDLBNrZ','CMvZDg9YzufNzw50','Dg9ju09tDhjPBMC','BwvZC2fNzq','zNvSBa','DgvYBwLUywW','BwTKAxi','tw9KzwWGy29UDMvYC2f0Aw9Uia','BwvZC2fNzxm','ndyZoti3nK5ICefbEa','ywDLBNrZl2fNzw50lq','zgvMyxvSDe1VzgvS','z2v0qwXSqxzHAwXHyMXLqwDLBNrZ','igLZig91DgrHDgvKlcb3AwXSihn5BMmGB24GBMv4Dcb1C2u','BMvLzhntEw5J','C3rYAw5NAwz5','zgvSzxrLqwDLBNrtDgf0zq','D2fYBG','C3rHDgveAxjLy3rVCNK','Aw5MBW','DgvZDa','C3rHDgvgAwXLCW','rMfPBgvKihrVihjLC3rVCMuGywDLBNq6ia','ndvMtMTnsMu','AxnqyxvZzwq','Bg9HzePtt04','C3LZDgvT','uhjVAMvJDcbYzxn1BwvKihn1y2nLC3nMDwXSEq','AM9PBG','mJy1mdi5oejPEfvprW','CMvZDg9YzunVBNrLEhrszwzLCMvUy2vZ','DgfZA0nVDw50','ywDLBNrjBMrLEa','igLZigfSCMvHzhKGBg9HzgvKlIbvC2uGC3DPDgnOqwDLBNqOksbPBNn0zwfKlG','mtK2zvDUwMPs','AxnmB2fKzwq','rMfPBgvKihrVigLUAxrPywXPEMuGC3rHDguGzgLYzwn0B3j5oIa','z2v0vgLTzq','ig5VDcbMB3vUzcbPBIbPBMrLEa','Bg9HzefNzw50sw5KzxG','ru5pru5u','C2f2zvbHDxnLzefNzw50','ywDLBNrZ','q2XLyw5Lzcb1CcbVBgqGC3rHDguGzMLSztOG','BMfTzq','ihrHC2TZ','C2f2zvbYB2PLy3rtDgf0zq','u3vJy2vZC2z1BgX5igLTCg9YDgvKigfNzw50ia','DMfSAwrHDgvnB2rLBenVBNzLCNnHDgLVBNm','lwnVBNzLCNnHDgLVBNmUANnVBG','y3DK','BwfW','ChjVAMvJDfn0yxrL','Cgf1C2vKqwDLBNrZ','B3bLCMf0Aw9UCY9WyxvZzwqTywDLBNrZlMPZB24','rMfPBgvKihrVigDLDcbHDMfPBgfIBguGywDLBNrZoIa','zgvIDwC','Cgf1C2viAxn0B3j5','C2f2zuPtt04','qwDLBNqG','odq2mZe0nhHotNb6Cq','zw50CMLLCW','CMvHzezPBgu','Cgf1C2vKqxq','BgfZDfvWzgf0zwq','z2v0uhjVAMvJDfn0yxrL','y29UDMvYC2f0Aw9UlwLUzgv4lMPZB24','DxbKyxrLqwDLBNrjBMrLEa','C2f2zuXHC3rtzxnZAw9U','BgvUz3rO','BgfZDc1ZzxnZAw9UlMPZB24','tg9HzgvKig1LDgfKyxrHigzVCIbHz2vUDca','mtu1mJy1D1nNrhPi','y29UDMvYC2f0Aw9UC0zPBgu','y2HLy2Tbz2vUDfbHDxnLu3rHDhvZ','u3rHDguGy2XLyw51CcbMywLSzwq6ia','rMfPBgvKihrVigrLBgv0zsbHz2vUDcbJB252zxjZyxrPB25ZigzPBgu6ia','B3bLCMf0Aw9UCW','ChvZAa','mty2otriu0H5sgG','lMXVEgLHlxn0yxrL','mJrTww5NwM8','sw1WB3j0Aw5NigfYy2HPDMvKigfNzw50oIa','y3jLyxrLzef0','y29UDgvUDa','z2v0qwDLBNrnzxrHzgf0yq','Cgf1C2vKvw50AwW','ody0mdy5mgrfvMXoAa','C3rHDgvwzxjZAw9U','C3rHDhvZ','C29YDa','ywDLBNqT','rMfPBgvKihrVihjLBw92zsbHz2vUDcbMCM9TigLUzgv4oIa','rMfPBgvKihrVigrLBgv0zsbHz2vUDcbZDgf0ztOG','DgfZA0XPC3q','CMvZDg9YzvbHDxnLzefNzw50CW','zgLYBMfTzq','D29YA2LUz0rPCMvJDg9YEq','CMvMzxjLBMnLCW','rMfPBgvKihrVihbLCNnPC3qGywDLBNqGC3rHDgu6ia','mtu0mtCWnxfYugzWva','C3rHDgvgAwXL','B3bLCMf0Aw9UCY90B29SlwHPC3rVCNKUANnVBG','CMvTB3zLrNjVBufNzw50sw5KzxG','BgfZDefJDgL2Axr5','Bg9HzfbYB2PLy3rtDgf0zq','Bg9Nz2vY','y2XLyw51Ce9Szfn0yxrL','CgvYC2LZDefNzw50u3rHDgu','BgfZDfnLC3nPB24','zxjYB3i','yNjVD3nLCG','Aw5PDgLHBgL6zvn0yxrLrgLYzwn0B3j5','y29Kzq','CMvHC29U','igfJDgL2zsWG','igf2ywLSywjSzsbHz2vUDhmGka','sw52ywXPzcbHz2vUDcbjrcbMB3jTyxq'];a0_0x54ea=function(){return _0x276e7e;};return a0_0x54ea();}class StateManager{constructor(_0x55ac24,_0x2305b2){const _0x47835a=a0_0xc826;this['config']=_0x55ac24,this[_0x47835a(0xa5)]=_0x2305b2,this['stateDirectory']=_0x55ac24[_0x47835a(0xcb)]?.['stateDirectory']||_0x47835a(0x8b),this[_0x47835a(0x93)]='1.0.0',this['stateFiles']={'projectState':'project-state.json','agentIndex':'agent-index.json','conversationIndex':_0x47835a(0xf3),'lastSession':_0x47835a(0xf7),'contextReferences':'context-references.json','asyncOperations':'operations/async-operations.json','pausedAgents':_0x47835a(0xe7),'toolHistory':_0x47835a(0xa1),'modelRouterCache':'models/model-router-cache.json','errorRecoveryLog':'models/error-recovery-log.json'};}async['initializeStateDirectory'](_0x2f32e7){const _0x3b49c1=a0_0xc826,_0x5c5299=a0_0x1280ea['join'](_0x2f32e7,this['stateDirectory']);try{await a0_0x8d03f4['mkdir'](_0x5c5299,{'recursive':!![]}),await a0_0x8d03f4[_0x3b49c1(0xb7)](a0_0x1280ea['join'](_0x5c5299,'agents'),{'recursive':!![]}),await a0_0x8d03f4['mkdir'](a0_0x1280ea[_0x3b49c1(0xcd)](_0x5c5299,_0x3b49c1(0x88)),{'recursive':!![]}),await a0_0x8d03f4[_0x3b49c1(0xb7)](a0_0x1280ea['join'](_0x5c5299,'models'),{'recursive':!![]}),this['logger'][_0x3b49c1(0xc4)]('State\x20directory\x20initialized:\x20'+_0x5c5299);}catch(_0x273044){this['logger']['error'](_0x3b49c1(0xd5)+_0x273044[_0x3b49c1(0xb4)]);throw _0x273044;}}async['resumeProject'](_0x21e36f){const _0xf58077=a0_0xc826;try{await this[_0xf58077(0xab)](_0x21e36f);const _0x4e3fee=await this['loadProjectState'](_0x21e36f),_0x3efcc5=await this['loadAgentIndex'](_0x21e36f),_0x1089fe=[];for(const [_0x16f6d1,_0x294b72]of Object[_0xf58077(0xee)](_0x3efcc5)){try{const _0x225b5c=await this[_0xf58077(0xb2)](_0x16f6d1,_0x294b72,_0x21e36f);_0x1089fe['push'](_0x225b5c);}catch(_0x274202){this[_0xf58077(0xa5)]['warn'](_0xf58077(0xc7)+_0x16f6d1,_0x274202['message']);}}const _0xc1a7c8=await this['restoreAsyncOperations'](_0x21e36f),_0x5afce3=await this['restorePausedAgents'](_0x21e36f),_0x1916fe=await this[_0xf58077(0xcf)](_0x21e36f),_0x2d98e5={'projectState':_0x4e3fee,'agents':_0x1089fe,'asyncOperations':_0xc1a7c8,'pausedAgents':_0x5afce3,'contextReferences':_0x1916fe,'resumedSuccessfully':!![],'resumedAt':new Date()[_0xf58077(0xb3)]()};return await this['saveLastSession'](_0x21e36f,{'resumedAt':new Date()['toISOString'](),'agentCount':_0x1089fe['length'],'operationCount':_0xc1a7c8['length']}),this[_0xf58077(0xa5)][_0xf58077(0xc4)](_0xf58077(0xcc),{'projectDir':_0x21e36f,'agentCount':_0x1089fe[_0xf58077(0xf6)],'operationCount':_0xc1a7c8['length']}),_0x2d98e5;}catch(_0x4c1124){return this['logger']['error']('Project\x20resume\x20failed:\x20'+_0x4c1124['message'],{'projectDir':_0x21e36f,'error':_0x4c1124['stack']}),{'projectState':null,'agents':[],'asyncOperations':[],'pausedAgents':[],'contextReferences':[],'resumedSuccessfully':![],'error':_0x4c1124['message']};}}async[a0_0x4baeee(0xa7)](_0x93c85d,_0x55dbae=process[a0_0x4baeee(0xe3)]()){const _0x5d8223=a0_0x4baeee,_0x2ee32c=a0_0x1280ea[_0x5d8223(0xcd)](_0x55dbae,this['stateDirectory']),_0x5c83af=a0_0x1280ea[_0x5d8223(0xcd)](_0x2ee32c,'agents','agent-'+_0x93c85d['id']+'-state.json'),_0x123397=a0_0x1280ea[_0x5d8223(0xcd)](_0x2ee32c,_0x5d8223(0xdb),_0x5d8223(0x96)+_0x93c85d['id']+'-conversations.json');try{const {conversations:_0x110f9f,..._0x491442}=_0x93c85d;await this['saveJSON'](_0x5c83af,{'version':this['stateVersion'],'agentId':_0x93c85d['id'],'state':_0x491442,'lastPersisted':new Date()['toISOString']()}),await this[_0x5d8223(0xeb)](_0x123397,{'version':this['stateVersion'],'agentId':_0x93c85d['id'],'conversations':_0x110f9f,'lastPersisted':new Date()['toISOString']()}),await this['updateAgentIndex'](_0x93c85d,_0x55dbae),this[_0x5d8223(0xa5)]['debug']('Agent\x20state\x20persisted:\x20'+_0x93c85d['id']);}catch(_0x5d97a1){this['logger'][_0x5d8223(0xa9)](_0x5d8223(0x9e)+_0x5d97a1[_0x5d8223(0xb4)],{'agentId':_0x93c85d['id'],'error':_0x5d97a1['stack']});throw _0x5d97a1;}}async[a0_0x4baeee(0xf2)](_0x5bd90c){const _0x1205e9=a0_0x4baeee;return await this[_0x1205e9(0xa4)](_0x5bd90c);}async['loadProjectState'](_0x3adfcc){const _0x55474e=a0_0x4baeee,_0x470dfb=a0_0x1280ea['join'](_0x3adfcc,this[_0x55474e(0xc3)],this[_0x55474e(0xc6)][_0x55474e(0xe5)]);try{const _0x45c6a2=await this['loadJSON'](_0x470dfb);return _0x45c6a2;}catch(_0x136d1b){const defaultState={'version':this['stateVersion'],'projectDir':_0x3adfcc,'createdAt':new Date()[_0x55474e(0xb3)](),'lastModified':new Date()[_0x55474e(0xb3)](),'activeAgents':[],'lastActiveSession':null,'configuration':{'defaultModel':this['config'][_0x55474e(0xcb)]?.[_0x55474e(0xbc)]||'anthropic-sonnet','allowedTools':[_0x55474e(0xb6),'filesystem',_0x55474e(0xaa)],'budgetLimit':0x64}};return await this[_0x55474e(0xdf)](_0x3adfcc,defaultState),defaultState;}}async['saveProjectState'](_0x1c306e,_0x4ef1b3){const _0x368189=a0_0x4baeee,_0x3fa53a=a0_0x1280ea['join'](_0x1c306e,this[_0x368189(0xc3)],this['stateFiles']['projectState']),_0x1ba88f={..._0x4ef1b3,'lastModified':new Date()[_0x368189(0xb3)]()};await this[_0x368189(0xeb)](_0x3fa53a,_0x1ba88f);}async['loadAgentIndex'](_0x3c28ee){const _0x4a0a65=a0_0x4baeee,_0x5c7c58=a0_0x1280ea[_0x4a0a65(0xcd)](_0x3c28ee,this[_0x4a0a65(0xc3)],this[_0x4a0a65(0xc6)]['agentIndex']);try{return await this['loadJSON'](_0x5c7c58);}catch(_0x41c2dd){return{};}}async['updateAgentIndex'](_0x2884a9,_0x56d7d9){const _0x554093=a0_0x4baeee,_0x4f0966=a0_0x1280ea[_0x554093(0xcd)](_0x56d7d9,this['stateDirectory'],this[_0x554093(0xc6)][_0x554093(0xd1)]);let _0x182416;try{_0x182416=await this['loadJSON'](_0x4f0966);}catch{_0x182416={};}_0x182416[_0x2884a9['id']]={'name':_0x2884a9['name'],'type':_0x2884a9['type'],'stateFile':'agents/agent-'+_0x2884a9['id']+'-state.json','conversationsFile':_0x554093(0xbb)+_0x2884a9['id']+'-conversations.json','lastActivity':_0x2884a9['lastActivity'],'model':_0x2884a9['currentModel'],'status':_0x2884a9['status']},await this[_0x554093(0xeb)](_0x4f0966,_0x182416);}async[a0_0x4baeee(0xb2)](_0x224389,_0x345a2e,_0x3d55c5){const _0x59f7e2=a0_0x4baeee,_0x38117d=a0_0x1280ea['join'](_0x3d55c5,this[_0x59f7e2(0xc3)]),_0x4cb54b=a0_0x1280ea['join'](_0x38117d,_0x345a2e['stateFile']),_0x1a6530=a0_0x1280ea[_0x59f7e2(0xcd)](_0x38117d,_0x345a2e[_0x59f7e2(0xfa)]);try{const _0xe00d66=await this['loadJSON'](_0x4cb54b),_0x2770d6=await this[_0x59f7e2(0xca)](_0x1a6530);await this['validateModelConversations'](_0x2770d6['conversations']);const _0x40ccf9=await this[_0x59f7e2(0xfb)](_0x224389,_0x3d55c5),_0x2184e3={..._0xe00d66['state'],'conversations':_0x2770d6['conversations'],'isPaused':_0x40ccf9[_0x59f7e2(0xc9)],'pausedUntil':_0x40ccf9[_0x59f7e2(0x91)],'isRestored':!![],'restoredAt':new Date()['toISOString']()};return this['logger']['info']('Agent\x20restored:\x20'+_0x224389,{'name':_0x2184e3[_0x59f7e2(0xdd)],'status':_0x2184e3[_0x59f7e2(0x94)],'messageCount':_0x2184e3['conversations']?.['full']?.[_0x59f7e2(0xb9)]?.['length']||0x0}),_0x2184e3;}catch(_0x54c14d){this['logger']['error']('Agent\x20restoration\x20failed:\x20'+_0x224389,_0x54c14d['message']);throw _0x54c14d;}}async['restoreAsyncOperations'](_0x94c431){const _0x3c8e9f=a0_0x4baeee,_0x1ae7e3=a0_0x1280ea[_0x3c8e9f(0xcd)](_0x94c431,this['stateDirectory'],this[_0x3c8e9f(0xc6)]['asyncOperations']);try{const _0x359ff3=await this['loadJSON'](_0x1ae7e3);return _0x359ff3['operations']||[];}catch{return[];}}async[a0_0x4baeee(0x9a)](_0x5370b3){const _0x51073d=a0_0x4baeee,_0x23ccb5=a0_0x1280ea[_0x51073d(0xcd)](_0x5370b3,this['stateDirectory'],this[_0x51073d(0xc6)][_0x51073d(0xe6)]);try{const _0x32dc01=await this['loadJSON'](_0x23ccb5),_0x1f95ab=Date['now'](),_0x5e02eb=[];for(const [_0x1a3912,_0x2139f6]of Object['entries'](_0x32dc01[_0x51073d(0xe6)]||{})){const _0x241572=new Date(_0x2139f6['pausedUntil'])[_0x51073d(0xd6)]();_0x1f95ab>=_0x241572&&_0x5e02eb['push'](_0x1a3912);}for(const _0x3ca9a9 of _0x5e02eb){const _0x599ec5=_0x32dc01['pausedAgents'][_0x3ca9a9];delete _0x32dc01['pausedAgents'][_0x3ca9a9],_0x32dc01[_0x51073d(0xea)]=_0x32dc01['pauseHistory']||[],_0x32dc01[_0x51073d(0xea)][_0x51073d(0x89)]({'agentId':_0x3ca9a9,'pausedAt':_0x599ec5[_0x51073d(0xf0)],'resumedAt':new Date()['toISOString'](),'reason':_0x599ec5[_0x51073d(0xad)],'actualDuration':Math['round']((_0x1f95ab-new Date(_0x599ec5[_0x51073d(0xf0)])['getTime']())/0x3e8)});}return await this['saveJSON'](_0x23ccb5,_0x32dc01),_0x32dc01;}catch{return{'pausedAgents':{},'pauseHistory':[]};}}async['restoreContextReferences'](_0x25130c){const _0x27fb39=a0_0x4baeee,_0x3c210d=a0_0x1280ea['join'](_0x25130c,this['stateDirectory'],this[_0x27fb39(0xc6)]['contextReferences']);try{const _0x16eaec=await this[_0x27fb39(0xca)](_0x3c210d),_0x35f664=[];for(const _0x3d6ba9 of _0x16eaec['references']||[]){_0x3d6ba9['isValid']=!![],_0x3d6ba9['lastValidated']=new Date()[_0x27fb39(0xb3)](),_0x35f664[_0x27fb39(0x89)](_0x3d6ba9);}return _0x16eaec[_0x27fb39(0x9d)]=_0x35f664,await this['saveJSON'](_0x3c210d,_0x16eaec),_0x16eaec;}catch{return{'references':[],'lastCleanup':new Date()[_0x27fb39(0xb3)]()};}}async[a0_0x4baeee(0xf5)](_0x26a97f,_0x12620a){const _0x4c1c1d=a0_0x4baeee,_0x4d359c=a0_0x1280ea[_0x4c1c1d(0xcd)](_0x26a97f,this[_0x4c1c1d(0xc3)],this[_0x4c1c1d(0xc6)]['lastSession']),_0x1b6b7d={..._0x12620a,'savedAt':new Date()['toISOString'](),'projectDir':_0x26a97f};await this[_0x4c1c1d(0xeb)](_0x4d359c,_0x1b6b7d);}async['loadLastSession'](_0x39f5d0){const _0x3c98de=a0_0x4baeee,_0x5092af=a0_0x1280ea['join'](_0x39f5d0,this[_0x3c98de(0xc3)],this[_0x3c98de(0xc6)][_0x3c98de(0xa8)]);try{return await this[_0x3c98de(0xca)](_0x5092af);}catch{return null;}}async[a0_0x4baeee(0xda)](_0x59f3ad,_0x34f8f0,_0xfb95ca){const _0x4c1649=a0_0x4baeee,_0x3a1d60=a0_0x1280ea[_0x4c1649(0xcd)](_0x59f3ad,this[_0x4c1649(0xc3)],this[_0x4c1649(0xc6)]['pausedAgents']);let _0x39a86f;try{_0x39a86f=await this[_0x4c1649(0xca)](_0x3a1d60);}catch{_0x39a86f={'pausedAgents':{},'pauseHistory':[]};}_0x39a86f['pausedAgents'][_0x34f8f0]=_0xfb95ca,await this[_0x4c1649(0xeb)](_0x3a1d60,_0x39a86f);}async['removePausedAgent'](_0x52da06,_0xb3a10d){const _0x2e1048=a0_0x4baeee,_0xdc4259=a0_0x1280ea[_0x2e1048(0xcd)](_0x52da06,this[_0x2e1048(0xc3)],this['stateFiles']['pausedAgents']);try{const _0x5e8773=await this[_0x2e1048(0xca)](_0xdc4259);delete _0x5e8773[_0x2e1048(0xe6)][_0xb3a10d],await this[_0x2e1048(0xeb)](_0xdc4259,_0x5e8773);}catch{}}async[a0_0x4baeee(0xfb)](_0x121685,_0x304ac2){const _0x10ad41=a0_0x4baeee,_0x242cfd=a0_0x1280ea['join'](_0x304ac2,this[_0x10ad41(0xc3)],this[_0x10ad41(0xc6)][_0x10ad41(0xe6)]);try{const _0x1ac9ee=await this['loadJSON'](_0x242cfd),_0x380c0e=_0x1ac9ee['pausedAgents'][_0x121685];if(!_0x380c0e)return{'isPaused':![],'pausedUntil':null};const _0x58d075=Date['now'](),_0x9ccd7c=new Date(_0x380c0e[_0x10ad41(0x91)])[_0x10ad41(0xd6)]();return{'isPaused':_0x58d075<_0x9ccd7c,'pausedUntil':_0x380c0e[_0x10ad41(0x91)],'reason':_0x380c0e[_0x10ad41(0xad)]};}catch{return{'isPaused':![],'pausedUntil':null};}}async[a0_0x4baeee(0xe1)](_0x54c8b4){const _0x47aea7=a0_0x4baeee;if(!_0x54c8b4||!_0x54c8b4['full'])throw new Error('Invalid\x20conversations\x20structure\x20-\x20missing\x20full\x20conversation');const _0x207276=_0x54c8b4['full']['messages']||[],_0x4b2e78=new Date(_0x54c8b4['full'][_0x47aea7(0xf1)]);for(const [_0x3aca3e,_0x38ae79]of Object[_0x47aea7(0xee)](_0x54c8b4)){if(_0x3aca3e===_0x47aea7(0xb5))continue;if(!_0x38ae79['messages']){this['logger'][_0x47aea7(0xc2)](_0x47aea7(0xb8)+_0x3aca3e+'\x20missing\x20messages\x20array');continue;}const _0x1e6ee8=new Date(_0x38ae79[_0x47aea7(0xf1)]);_0x4b2e78>_0x1e6ee8&&(this[_0x47aea7(0xa5)][_0x47aea7(0xc2)]('Model\x20conversation\x20'+_0x3aca3e+_0x47aea7(0xbe)),_0x38ae79[_0x47aea7(0xbf)]=!![]);}}async[a0_0x4baeee(0xeb)](_0x2b8817,_0x59bfb4){const _0x50c53c=a0_0x4baeee,_0x251030=a0_0x1280ea[_0x50c53c(0x9b)](_0x2b8817);await a0_0x8d03f4[_0x50c53c(0xb7)](_0x251030,{'recursive':!![]});const _0x45cb13=JSON[_0x50c53c(0xc0)](_0x59bfb4,null,0x2);await a0_0x8d03f4['writeFile'](_0x2b8817,_0x45cb13,'utf8');}async[a0_0x4baeee(0xca)](_0x2ad1f9){const _0x3e6edb=a0_0x4baeee,_0x2a7998=await a0_0x8d03f4[_0x3e6edb(0xef)](_0x2ad1f9,'utf8');return JSON['parse'](_0x2a7998);}async[a0_0x4baeee(0xc1)](_0x5108d7,_0x4ba307=process['cwd']()){const _0x2f6d36=a0_0x4baeee,_0x4a0f96=a0_0x1280ea[_0x2f6d36(0xcd)](_0x4ba307,this[_0x2f6d36(0xc3)]),_0x24edb2=a0_0x1280ea['join'](_0x4a0f96,'agents',_0x2f6d36(0x96)+_0x5108d7+'-state.json'),_0x4c9d5a=a0_0x1280ea['join'](_0x4a0f96,'agents',_0x2f6d36(0x96)+_0x5108d7+_0x2f6d36(0xe2));try{try{await a0_0x8d03f4['unlink'](_0x24edb2),this['logger']['debug']('Deleted\x20agent\x20state\x20file:\x20'+_0x5108d7);}catch(_0x2d42f1){_0x2d42f1[_0x2f6d36(0xac)]!=='ENOENT'&&this['logger'][_0x2f6d36(0xc2)]('Failed\x20to\x20delete\x20agent\x20state\x20file:\x20'+_0x2d42f1['message'],{'agentId':_0x5108d7});}try{await a0_0x8d03f4['unlink'](_0x4c9d5a),this['logger'][_0x2f6d36(0xe9)]('Deleted\x20agent\x20conversations\x20file:\x20'+_0x5108d7);}catch(_0x4f7567){_0x4f7567['code']!==_0x2f6d36(0xd9)&&this[_0x2f6d36(0xa5)]['warn'](_0x2f6d36(0xfd)+_0x4f7567[_0x2f6d36(0xb4)],{'agentId':_0x5108d7});}await this[_0x2f6d36(0xa2)](_0x5108d7,_0x4ba307),this[_0x2f6d36(0xa5)][_0x2f6d36(0xc4)]('Agent\x20state\x20deleted:\x20'+_0x5108d7);}catch(_0x1108fa){this[_0x2f6d36(0xa5)][_0x2f6d36(0xa9)](_0x2f6d36(0x98)+_0x1108fa[_0x2f6d36(0xb4)],{'agentId':_0x5108d7,'error':_0x1108fa['stack']});throw _0x1108fa;}}async[a0_0x4baeee(0xa2)](_0x2abe38,_0x1e0cbc){const _0x4b8de7=a0_0x4baeee,_0x5085ea=a0_0x1280ea[_0x4b8de7(0xcd)](_0x1e0cbc,this[_0x4b8de7(0xc3)],this[_0x4b8de7(0xc6)][_0x4b8de7(0xd1)]);try{const _0x4d0cc4=await this['loadJSON'](_0x5085ea);delete _0x4d0cc4[_0x2abe38],await this[_0x4b8de7(0xeb)](_0x5085ea,_0x4d0cc4),this[_0x4b8de7(0xa5)][_0x4b8de7(0xe9)]('Removed\x20agent\x20from\x20index:\x20'+_0x2abe38);}catch(_0x2b6bab){this['logger'][_0x4b8de7(0xc2)](_0x4b8de7(0x97)+_0x2b6bab[_0x4b8de7(0xb4)],{'agentId':_0x2abe38});}}async['stateDirectoryExists'](_0x15a720){const _0x22102a=a0_0x1280ea['join'](_0x15a720,this['stateDirectory']);try{const _0x523972=await a0_0x8d03f4['stat'](_0x22102a);return _0x523972['isDirectory']();}catch{return![];}}async[a0_0x4baeee(0xa6)](_0x4712a2,_0x184c0b=0x1e){const _0x37d56b=a0_0x4baeee,_0x38e786=a0_0x1280ea[_0x37d56b(0xcd)](_0x4712a2,this['stateDirectory']),_0x3e4248=Date['now']()-_0x184c0b*0x18*0x3c*0x3c*0x3e8;try{const _0x444c62=a0_0x1280ea[_0x37d56b(0xcd)](_0x38e786,'agents'),_0x31b139=await a0_0x8d03f4['readdir'](_0x444c62);for(const _0x337498 of _0x31b139){const _0x3d4c47=a0_0x1280ea[_0x37d56b(0xcd)](_0x444c62,_0x337498),_0x25d924=await a0_0x8d03f4['stat'](_0x3d4c47);_0x25d924['mtime'][_0x37d56b(0xd6)]()<_0x3e4248&&(await a0_0x8d03f4['unlink'](_0x3d4c47),this[_0x37d56b(0xa5)][_0x37d56b(0xc4)](_0x37d56b(0xdc)+_0x337498));}}catch(_0x2d4b1b){this['logger'][_0x37d56b(0xc2)](_0x37d56b(0xfc)+_0x2d4b1b['message']);}}async[a0_0x4baeee(0xbd)](_0x4bb38c,_0x2a7ac0){const _0x4653c7=a0_0x4baeee;try{const _0x5ed1c1=await this[_0x4653c7(0xd8)](_0x4bb38c),_0x4f90aa=_0x2a7ac0?(await _0x2a7ac0[_0x4653c7(0xb1)]())[_0x4653c7(0xe4)](_0x5d722d=>_0x5d722d['id']):[],_0x5f1452=[];for(const [_0x3c71f6,_0x2709e6]of Object['entries'](_0x5ed1c1)){if(!_0x2709e6||!_0x2709e6['name'])continue;_0x5f1452['push']({'agentId':_0x3c71f6,'name':_0x2709e6[_0x4653c7(0xdd)],'type':_0x2709e6['type'],'model':_0x2709e6['model'],'lastActivity':_0x2709e6[_0x4653c7(0xa3)],'status':_0x2709e6['status'],'stateFile':_0x2709e6[_0x4653c7(0xa0)],'conversationsFile':_0x2709e6['conversationsFile'],'isLoaded':_0x4f90aa['includes'](_0x3c71f6),'canImport':!_0x4f90aa['includes'](_0x3c71f6)});}return _0x5f1452[_0x4653c7(0x95)]((_0x10c177,_0x99880)=>{const _0x5c737e=_0x4653c7,_0x28deac=_0x10c177[_0x5c737e(0xa3)]?new Date(_0x10c177[_0x5c737e(0xa3)]):new Date(0x0),_0x5e8292=_0x99880[_0x5c737e(0xa3)]?new Date(_0x99880[_0x5c737e(0xa3)]):new Date(0x0);return _0x5e8292-_0x28deac;}),this['logger'][_0x4653c7(0xc4)]('Found\x20'+_0x5f1452['length']+_0x4653c7(0xaf)+_0x5f1452['filter'](_0x160037=>_0x160037['isLoaded'])['length']+_0x4653c7(0xae)+_0x5f1452['filter'](_0x508da7=>!_0x508da7[_0x4653c7(0xd4)])['length']+'\x20archived)'),_0x5f1452;}catch(_0x238d5c){this[_0x4653c7(0xa5)]['error'](_0x4653c7(0xe8)+_0x238d5c[_0x4653c7(0xb4)]);throw _0x238d5c;}}async[a0_0x4baeee(0x90)](_0x47cbde,_0x9e3381){const _0x1d31b2=a0_0x4baeee;try{const _0x4efc11=await this['loadAgentIndex'](_0x9e3381),_0x2c6154=_0x4efc11[_0x47cbde];if(!_0x2c6154)throw new Error(_0x1d31b2(0xec)+_0x47cbde+_0x1d31b2(0xd7));const _0x24acb6=a0_0x1280ea['join'](_0x9e3381,this[_0x1d31b2(0xc3)]),_0x509b94=a0_0x1280ea['join'](_0x24acb6,_0x2c6154['stateFile']),_0x4c9596=a0_0x1280ea['join'](_0x24acb6,_0x2c6154['conversationsFile']),_0x2c5072=await a0_0x8d03f4['access'](_0x509b94)['then'](()=>!![])['catch'](()=>![]),_0x1bafcb=await a0_0x8d03f4['access'](_0x4c9596)['then'](()=>!![])['catch'](()=>![]);if(!_0x2c5072)throw new Error('State\x20file\x20not\x20found\x20for\x20agent\x20'+_0x47cbde);const _0x13b275=await this[_0x1d31b2(0xca)](_0x509b94),_0x535ff=_0x13b275['state']||{};let _0x344fa0=0x0,_0x16b969=null;if(_0x1bafcb)try{const _0x4746f2=await this[_0x1d31b2(0xca)](_0x4c9596);_0x344fa0=Array['isArray'](_0x4746f2)?_0x4746f2[_0x1d31b2(0xf6)]:0x0;if(_0x344fa0>0x0){const _0x58f4e7=_0x4746f2[_0x4746f2['length']-0x1];_0x16b969=_0x58f4e7?.[_0x1d31b2(0x8f)]?.['substring'](0x0,0x64)||null;}}catch(_0x1c9c5a){this['logger']['warn']('Failed\x20to\x20load\x20conversations\x20for\x20'+_0x47cbde+':\x20'+_0x1c9c5a[_0x1d31b2(0xb4)]);}const _0x191358={'agentId':_0x47cbde,'name':_0x2c6154[_0x1d31b2(0xdd)]||_0x535ff[_0x1d31b2(0xdd)],'model':_0x2c6154['model']||_0x535ff['preferredModel']||_0x535ff['currentModel'],'lastActivity':_0x2c6154['lastActivity'],'status':_0x2c6154[_0x1d31b2(0x94)],'capabilities':_0x535ff['capabilities']||[],'messageCount':_0x344fa0,'lastMessage':_0x16b969,'taskCount':_0x535ff[_0x1d31b2(0x99)]?.['tasks']?.['length']||0x0,'createdAt':_0x535ff[_0x1d31b2(0x8e)],'workingDirectory':_0x535ff['directoryAccess']?.[_0x1d31b2(0x9c)],'mode':_0x535ff['mode'],'systemPrompt':_0x535ff['originalSystemPrompt']};return this['logger']['info'](_0x1d31b2(0xf8)+_0x47cbde+':\x20'+_0x191358['messageCount']+'\x20messages,\x20'+_0x191358[_0x1d31b2(0xd0)]+_0x1d31b2(0xde)),_0x191358;}catch(_0x258ff3){this['logger'][_0x1d31b2(0xa9)]('Failed\x20to\x20get\x20agent\x20metadata\x20for\x20'+_0x47cbde+':\x20'+_0x258ff3['message']);throw _0x258ff3;}}async['importArchivedAgent'](_0xfabd56,_0xf37d2,_0x2af45e){const _0x145b7a=a0_0x4baeee;try{const _0x24d544=/^agent-[a-z0-9-]+-\d+$/;if(!_0x24d544[_0x145b7a(0xc5)](_0xfabd56))throw new Error(_0x145b7a(0xb0));if(_0x2af45e&&await _0x2af45e['getAgent'](_0xfabd56))throw new Error('Agent\x20'+_0xfabd56+_0x145b7a(0xd2));const _0x4d9715=await this[_0x145b7a(0xd8)](_0xf37d2),_0x3e7e05=_0x4d9715[_0xfabd56];if(!_0x3e7e05)throw new Error('Agent\x20'+_0xfabd56+_0x145b7a(0xd7));this['logger'][_0x145b7a(0xc4)](_0x145b7a(0x8d)+_0xfabd56+'\x20('+_0x3e7e05['name']+')');const _0x1f37af=await this['restoreAgent'](_0xfabd56,_0x3e7e05,_0xf37d2);return _0x1f37af['lastActivity']=new Date()['toISOString'](),_0x2af45e&&(_0x2af45e[_0x145b7a(0xdb)]['set'](_0x1f37af['id'],_0x1f37af),_0x2af45e['_updateAgentDirectory'](_0x1f37af),this[_0x145b7a(0xa5)][_0x145b7a(0xc4)]('Agent\x20'+_0xfabd56+'\x20added\x20to\x20agent\x20pool')),await this[_0x145b7a(0xf4)](_0x1f37af,_0xf37d2),this[_0x145b7a(0xa5)][_0x145b7a(0xc4)](_0x145b7a(0xe0)+_0xfabd56+':\x20'+_0x1f37af[_0x145b7a(0xdd)]),_0x1f37af;}catch(_0x5a5289){this[_0x145b7a(0xa5)]['error']('Failed\x20to\x20import\x20agent\x20'+_0xfabd56+':\x20'+_0x5a5289['message']);throw _0x5a5289;}}}function a0_0xc826(_0x3f06eb,_0x508581){_0x3f06eb=_0x3f06eb-0x88;const _0x54ea9d=a0_0x54ea();let _0xc82671=_0x54ea9d[_0x3f06eb];if(a0_0xc826['AbmYDv']===undefined){var _0x105bcf=function(_0x46b342){const _0x120bd2='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';let _0x8d03f4='',_0x1280ea='';for(let _0x55ac24=0x0,_0x2305b2,_0x2f32e7,_0x5c5299=0x0;_0x2f32e7=_0x46b342['charAt'](_0x5c5299++);~_0x2f32e7&&(_0x2305b2=_0x55ac24%0x4?_0x2305b2*0x40+_0x2f32e7:_0x2f32e7,_0x55ac24++%0x4)?_0x8d03f4+=String['fromCharCode'](0xff&_0x2305b2>>(-0x2*_0x55ac24&0x6)):0x0){_0x2f32e7=_0x120bd2['indexOf'](_0x2f32e7);}for(let _0x273044=0x0,_0x21e36f=_0x8d03f4['length'];_0x273044<_0x21e36f;_0x273044++){_0x1280ea+='%'+('00'+_0x8d03f4['charCodeAt'](_0x273044)['toString'](0x10))['slice'](-0x2);}return decodeURIComponent(_0x1280ea);};a0_0xc826['PZFXJB']=_0x105bcf,a0_0xc826['MULzvO']={},a0_0xc826['AbmYDv']=!![];}const _0x3cd739=_0x54ea9d[0x0],_0xf80cef=_0x3f06eb+_0x3cd739,_0x2b6e91=a0_0xc826['MULzvO'][_0xf80cef];return!_0x2b6e91?(_0xc82671=a0_0xc826['PZFXJB'](_0xc82671),a0_0xc826['MULzvO'][_0xf80cef]=_0xc82671):_0xc82671=_0x2b6e91,_0xc82671;}export default StateManager;
|