@loxia-labs/loxia-autopilot-one 1.0.1 → 1.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +44 -54
- package/bin/cli.js +1 -115
- package/bin/loxia-terminal-v2.js +3 -0
- package/bin/loxia-terminal.js +3 -0
- package/bin/start-with-terminal.js +3 -0
- package/package.json +14 -15
- package/scripts/install-scanners.js +1 -235
- package/src/analyzers/CSSAnalyzer.js +1 -297
- package/src/analyzers/ConfigValidator.js +1 -690
- package/src/analyzers/ESLintAnalyzer.js +1 -320
- package/src/analyzers/JavaScriptAnalyzer.js +1 -261
- package/src/analyzers/PrettierFormatter.js +1 -247
- package/src/analyzers/PythonAnalyzer.js +1 -266
- package/src/analyzers/SecurityAnalyzer.js +1 -729
- package/src/analyzers/TypeScriptAnalyzer.js +1 -247
- package/src/analyzers/codeCloneDetector/analyzer.js +1 -344
- package/src/analyzers/codeCloneDetector/detector.js +1 -203
- package/src/analyzers/codeCloneDetector/index.js +1 -160
- package/src/analyzers/codeCloneDetector/parser.js +1 -199
- package/src/analyzers/codeCloneDetector/reporter.js +1 -148
- package/src/analyzers/codeCloneDetector/scanner.js +1 -59
- package/src/core/agentPool.js +1 -1474
- package/src/core/agentScheduler.js +1 -2147
- package/src/core/contextManager.js +1 -709
- package/src/core/messageProcessor.js +1 -732
- package/src/core/orchestrator.js +1 -548
- package/src/core/stateManager.js +1 -877
- package/src/index.js +1 -631
- package/src/interfaces/cli.js +1 -549
- package/src/interfaces/terminal/__tests__/smoke/advancedFeatures.test.js +1 -0
- package/src/interfaces/terminal/__tests__/smoke/agentControl.test.js +1 -0
- package/src/interfaces/terminal/__tests__/smoke/agents.test.js +1 -0
- package/src/interfaces/terminal/__tests__/smoke/components.test.js +1 -0
- package/src/interfaces/terminal/__tests__/smoke/connection.test.js +1 -0
- package/src/interfaces/terminal/__tests__/smoke/enhancements.test.js +1 -0
- package/src/interfaces/terminal/__tests__/smoke/imports.test.js +1 -0
- package/src/interfaces/terminal/__tests__/smoke/messages.test.js +1 -0
- package/src/interfaces/terminal/__tests__/smoke/tools.test.js +1 -0
- package/src/interfaces/terminal/api/apiClient.js +1 -0
- package/src/interfaces/terminal/api/messageRouter.js +1 -0
- package/src/interfaces/terminal/api/session.js +1 -0
- package/src/interfaces/terminal/api/websocket.js +1 -0
- package/src/interfaces/terminal/components/AgentCreator.js +1 -0
- package/src/interfaces/terminal/components/AgentEditor.js +1 -0
- package/src/interfaces/terminal/components/AgentSwitcher.js +1 -0
- package/src/interfaces/terminal/components/ErrorBoundary.js +1 -0
- package/src/interfaces/terminal/components/ErrorPanel.js +1 -0
- package/src/interfaces/terminal/components/Header.js +1 -0
- package/src/interfaces/terminal/components/HelpPanel.js +1 -0
- package/src/interfaces/terminal/components/InputBox.js +1 -0
- package/src/interfaces/terminal/components/Layout.js +1 -0
- package/src/interfaces/terminal/components/LoadingSpinner.js +1 -0
- package/src/interfaces/terminal/components/MessageList.js +1 -0
- package/src/interfaces/terminal/components/MultilineTextInput.js +1 -0
- package/src/interfaces/terminal/components/SearchPanel.js +1 -0
- package/src/interfaces/terminal/components/SettingsPanel.js +1 -0
- package/src/interfaces/terminal/components/StatusBar.js +1 -0
- package/src/interfaces/terminal/components/TextInput.js +1 -0
- package/src/interfaces/terminal/config/agentEditorConstants.js +1 -0
- package/src/interfaces/terminal/config/constants.js +1 -0
- package/src/interfaces/terminal/index.js +1 -0
- package/src/interfaces/terminal/state/useAgentControl.js +1 -0
- package/src/interfaces/terminal/state/useAgents.js +1 -0
- package/src/interfaces/terminal/state/useConnection.js +1 -0
- package/src/interfaces/terminal/state/useMessages.js +1 -0
- package/src/interfaces/terminal/state/useTools.js +1 -0
- package/src/interfaces/terminal/utils/debugLogger.js +1 -0
- package/src/interfaces/terminal/utils/settingsStorage.js +1 -0
- package/src/interfaces/terminal/utils/theme.js +1 -0
- package/src/interfaces/webServer.js +1 -2162
- package/src/modules/fileExplorer/controller.js +1 -280
- package/src/modules/fileExplorer/index.js +1 -37
- package/src/modules/fileExplorer/middleware.js +1 -92
- package/src/modules/fileExplorer/routes.js +1 -125
- package/src/modules/fileExplorer/types.js +1 -44
- package/src/services/aiService.js +1 -1232
- package/src/services/apiKeyManager.js +1 -164
- package/src/services/benchmarkService.js +1 -366
- package/src/services/budgetService.js +1 -539
- package/src/services/contextInjectionService.js +1 -247
- package/src/services/conversationCompactionService.js +1 -637
- package/src/services/errorHandler.js +1 -810
- package/src/services/fileAttachmentService.js +1 -544
- package/src/services/modelRouterService.js +1 -366
- package/src/services/modelsService.js +1 -322
- package/src/services/qualityInspector.js +1 -796
- package/src/services/tokenCountingService.js +1 -536
- package/src/tools/agentCommunicationTool.js +1 -1344
- package/src/tools/agentDelayTool.js +1 -485
- package/src/tools/asyncToolManager.js +1 -604
- package/src/tools/baseTool.js +1 -800
- package/src/tools/browserTool.js +1 -920
- package/src/tools/cloneDetectionTool.js +1 -621
- package/src/tools/dependencyResolverTool.js +1 -1215
- package/src/tools/fileContentReplaceTool.js +1 -875
- package/src/tools/fileSystemTool.js +1 -1107
- package/src/tools/fileTreeTool.js +1 -853
- package/src/tools/imageTool.js +1 -901
- package/src/tools/importAnalyzerTool.js +1 -1060
- package/src/tools/jobDoneTool.js +1 -248
- package/src/tools/seekTool.js +1 -956
- package/src/tools/staticAnalysisTool.js +1 -1778
- package/src/tools/taskManagerTool.js +1 -2873
- package/src/tools/terminalTool.js +1 -2304
- package/src/tools/webTool.js +1 -1430
- package/src/types/agent.js +1 -519
- package/src/types/contextReference.js +1 -972
- package/src/types/conversation.js +1 -730
- package/src/types/toolCommand.js +1 -747
- package/src/utilities/attachmentValidator.js +1 -292
- package/src/utilities/configManager.js +1 -582
- package/src/utilities/constants.js +1 -722
- package/src/utilities/directoryAccessManager.js +1 -535
- package/src/utilities/fileProcessor.js +1 -307
- package/src/utilities/logger.js +1 -436
- package/src/utilities/tagParser.js +1 -1246
- package/src/utilities/toolConstants.js +1 -317
- package/web-ui/build/index.html +2 -2
- package/web-ui/build/static/{index-Dy2bYbOa.css → index-CClD1090.css} +1 -1
- package/web-ui/build/static/{index-CjkkcnFA.js → index-lCBai6dX.js} +66 -67
|
@@ -1,582 +1 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* ConfigManager - Centralized configuration management for the Loxia AI Agents System
|
|
3
|
-
*
|
|
4
|
-
* Purpose:
|
|
5
|
-
* - Load and merge configuration from multiple sources
|
|
6
|
-
* - Environment variable support
|
|
7
|
-
* - Configuration validation
|
|
8
|
-
* - Runtime configuration updates
|
|
9
|
-
* - Default configuration management
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
import { promises as fs } from 'fs';
|
|
13
|
-
import path from 'path';
|
|
14
|
-
|
|
15
|
-
import {
|
|
16
|
-
SYSTEM_DEFAULTS,
|
|
17
|
-
MODELS,
|
|
18
|
-
MODEL_ROUTING,
|
|
19
|
-
TOOL_NAMES,
|
|
20
|
-
STATE_DIRECTORIES,
|
|
21
|
-
ERROR_TYPES
|
|
22
|
-
} from './constants.js';
|
|
23
|
-
|
|
24
|
-
class ConfigManager {
|
|
25
|
-
constructor(options = {}) {
|
|
26
|
-
this.configPaths = options.configPaths || [];
|
|
27
|
-
this.envPrefix = options.envPrefix || 'LOXIA';
|
|
28
|
-
this.config = {};
|
|
29
|
-
this.watchers = new Map();
|
|
30
|
-
this.changeListeners = new Set();
|
|
31
|
-
|
|
32
|
-
// Default configuration
|
|
33
|
-
this.defaultConfig = this.getDefaultConfig();
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* Load configuration from all sources
|
|
38
|
-
* @returns {Promise<Object>} Loaded configuration
|
|
39
|
-
*/
|
|
40
|
-
async loadConfig() {
|
|
41
|
-
let config = { ...this.defaultConfig };
|
|
42
|
-
|
|
43
|
-
// Load from config files
|
|
44
|
-
for (const configPath of this.configPaths) {
|
|
45
|
-
try {
|
|
46
|
-
const fileConfig = await this.loadConfigFile(configPath);
|
|
47
|
-
config = this.mergeConfig(config, fileConfig);
|
|
48
|
-
} catch (error) {
|
|
49
|
-
console.warn(`Failed to load config file ${configPath}:`, error.message);
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
// Override with environment variables
|
|
54
|
-
const envConfig = this.loadEnvironmentConfig();
|
|
55
|
-
config = this.mergeConfig(config, envConfig);
|
|
56
|
-
|
|
57
|
-
// Validate configuration
|
|
58
|
-
const validation = this.validateConfig(config);
|
|
59
|
-
if (!validation.valid) {
|
|
60
|
-
throw new Error(`Configuration validation failed: ${validation.errors.join(', ')}`);
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
// Apply configuration transformations
|
|
64
|
-
config = this.transformConfig(config);
|
|
65
|
-
|
|
66
|
-
this.config = config;
|
|
67
|
-
|
|
68
|
-
// Notify listeners of config change
|
|
69
|
-
this.notifyConfigChange(config);
|
|
70
|
-
|
|
71
|
-
return config;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
/**
|
|
75
|
-
* Get current configuration
|
|
76
|
-
* @returns {Object} Current configuration
|
|
77
|
-
*/
|
|
78
|
-
getConfig() {
|
|
79
|
-
return { ...this.config };
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
/**
|
|
83
|
-
* Get configuration value by path
|
|
84
|
-
* @param {string} path - Configuration path (e.g., 'system.maxAgentsPerProject')
|
|
85
|
-
* @param {*} defaultValue - Default value if path not found
|
|
86
|
-
* @returns {*} Configuration value
|
|
87
|
-
*/
|
|
88
|
-
get(path, defaultValue = undefined) {
|
|
89
|
-
const keys = path.split('.');
|
|
90
|
-
let value = this.config;
|
|
91
|
-
|
|
92
|
-
for (const key of keys) {
|
|
93
|
-
if (value && typeof value === 'object' && key in value) {
|
|
94
|
-
value = value[key];
|
|
95
|
-
} else {
|
|
96
|
-
return defaultValue;
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
return value;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
/**
|
|
104
|
-
* Set configuration value by path
|
|
105
|
-
* @param {string} path - Configuration path
|
|
106
|
-
* @param {*} value - Value to set
|
|
107
|
-
*/
|
|
108
|
-
set(path, value) {
|
|
109
|
-
const keys = path.split('.');
|
|
110
|
-
const lastKey = keys.pop();
|
|
111
|
-
let target = this.config;
|
|
112
|
-
|
|
113
|
-
// Navigate to parent object
|
|
114
|
-
for (const key of keys) {
|
|
115
|
-
if (!(key in target) || typeof target[key] !== 'object') {
|
|
116
|
-
target[key] = {};
|
|
117
|
-
}
|
|
118
|
-
target = target[key];
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
target[lastKey] = value;
|
|
122
|
-
|
|
123
|
-
// Notify listeners of config change
|
|
124
|
-
this.notifyConfigChange(this.config);
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
/**
|
|
128
|
-
* Watch configuration files for changes
|
|
129
|
-
* @param {boolean} enable - Enable or disable watching
|
|
130
|
-
* @returns {Promise<void>}
|
|
131
|
-
*/
|
|
132
|
-
async watchConfig(enable = true) {
|
|
133
|
-
if (!enable) {
|
|
134
|
-
// Stop all watchers
|
|
135
|
-
for (const [filePath, watcher] of this.watchers) {
|
|
136
|
-
watcher.close();
|
|
137
|
-
this.watchers.delete(filePath);
|
|
138
|
-
}
|
|
139
|
-
return;
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
// Start watching config files
|
|
143
|
-
for (const configPath of this.configPaths) {
|
|
144
|
-
if (this.watchers.has(configPath)) continue;
|
|
145
|
-
|
|
146
|
-
try {
|
|
147
|
-
const { watch } = await import('fs');
|
|
148
|
-
const watcher = watch(configPath, async (eventType) => {
|
|
149
|
-
if (eventType === 'change') {
|
|
150
|
-
try {
|
|
151
|
-
await this.loadConfig();
|
|
152
|
-
} catch (error) {
|
|
153
|
-
console.error(`Failed to reload config after change in ${configPath}:`, error.message);
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
});
|
|
157
|
-
|
|
158
|
-
this.watchers.set(configPath, watcher);
|
|
159
|
-
} catch (error) {
|
|
160
|
-
console.warn(`Failed to watch config file ${configPath}:`, error.message);
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
/**
|
|
166
|
-
* Add configuration change listener
|
|
167
|
-
* @param {Function} listener - Change listener function
|
|
168
|
-
*/
|
|
169
|
-
addChangeListener(listener) {
|
|
170
|
-
this.changeListeners.add(listener);
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
/**
|
|
174
|
-
* Remove configuration change listener
|
|
175
|
-
* @param {Function} listener - Change listener function
|
|
176
|
-
*/
|
|
177
|
-
removeChangeListener(listener) {
|
|
178
|
-
this.changeListeners.delete(listener);
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
/**
|
|
182
|
-
* Load configuration from file
|
|
183
|
-
* @private
|
|
184
|
-
*/
|
|
185
|
-
async loadConfigFile(filePath) {
|
|
186
|
-
try {
|
|
187
|
-
const content = await fs.readFile(filePath, 'utf8');
|
|
188
|
-
|
|
189
|
-
const ext = path.extname(filePath).toLowerCase();
|
|
190
|
-
switch (ext) {
|
|
191
|
-
case '.json':
|
|
192
|
-
return JSON.parse(content);
|
|
193
|
-
|
|
194
|
-
case '.js':
|
|
195
|
-
// For .js files, use dynamic import
|
|
196
|
-
const fullPath = path.resolve(filePath);
|
|
197
|
-
const module = await import(fullPath);
|
|
198
|
-
return module.default || module;
|
|
199
|
-
|
|
200
|
-
case '.yaml':
|
|
201
|
-
case '.yml':
|
|
202
|
-
// Would need yaml parser dependency
|
|
203
|
-
throw new Error('YAML configuration files not supported in this implementation');
|
|
204
|
-
|
|
205
|
-
default:
|
|
206
|
-
throw new Error(`Unsupported configuration file format: ${ext}`);
|
|
207
|
-
}
|
|
208
|
-
} catch (error) {
|
|
209
|
-
throw new Error(`Failed to load config file ${filePath}: ${error.message}`);
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
/**
|
|
214
|
-
* Load configuration from environment variables
|
|
215
|
-
* @private
|
|
216
|
-
*/
|
|
217
|
-
loadEnvironmentConfig() {
|
|
218
|
-
const envConfig = {};
|
|
219
|
-
|
|
220
|
-
// Map environment variables to config paths
|
|
221
|
-
const envMappings = {
|
|
222
|
-
[`${this.envPrefix}_API_KEY`]: 'apiKey',
|
|
223
|
-
[`${this.envPrefix}_LOG_LEVEL`]: 'logging.level',
|
|
224
|
-
[`${this.envPrefix}_MAX_AGENTS`]: 'system.maxAgentsPerProject',
|
|
225
|
-
[`${this.envPrefix}_DEFAULT_MODEL`]: 'system.defaultModel',
|
|
226
|
-
[`${this.envPrefix}_BACKEND_URL`]: 'backend.baseUrl',
|
|
227
|
-
[`${this.envPrefix}_BACKEND_TIMEOUT`]: 'backend.timeout',
|
|
228
|
-
[`${this.envPrefix}_STATE_DIR`]: 'system.stateDirectory',
|
|
229
|
-
[`${this.envPrefix}_BUDGET_LIMIT`]: 'budget.limit',
|
|
230
|
-
[`${this.envPrefix}_TOOLS_ENABLED`]: 'tools.enabled'
|
|
231
|
-
};
|
|
232
|
-
|
|
233
|
-
for (const [envVar, configPath] of Object.entries(envMappings)) {
|
|
234
|
-
const value = process.env[envVar];
|
|
235
|
-
if (value !== undefined) {
|
|
236
|
-
this.setNestedValue(envConfig, configPath, this.parseEnvValue(value));
|
|
237
|
-
}
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
return envConfig;
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
/**
|
|
244
|
-
* Parse environment variable value
|
|
245
|
-
* @private
|
|
246
|
-
*/
|
|
247
|
-
parseEnvValue(value) {
|
|
248
|
-
// Try to parse as JSON first
|
|
249
|
-
try {
|
|
250
|
-
return JSON.parse(value);
|
|
251
|
-
} catch {
|
|
252
|
-
// Return as string if not valid JSON
|
|
253
|
-
return value;
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
/**
|
|
258
|
-
* Set nested object value by path
|
|
259
|
-
* @private
|
|
260
|
-
*/
|
|
261
|
-
setNestedValue(obj, path, value) {
|
|
262
|
-
const keys = path.split('.');
|
|
263
|
-
const lastKey = keys.pop();
|
|
264
|
-
let target = obj;
|
|
265
|
-
|
|
266
|
-
for (const key of keys) {
|
|
267
|
-
if (!(key in target)) {
|
|
268
|
-
target[key] = {};
|
|
269
|
-
}
|
|
270
|
-
target = target[key];
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
target[lastKey] = value;
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
/**
|
|
277
|
-
* Merge configuration objects
|
|
278
|
-
* @private
|
|
279
|
-
*/
|
|
280
|
-
mergeConfig(base, override) {
|
|
281
|
-
const result = { ...base };
|
|
282
|
-
|
|
283
|
-
for (const [key, value] of Object.entries(override)) {
|
|
284
|
-
if (value && typeof value === 'object' && !Array.isArray(value)) {
|
|
285
|
-
result[key] = this.mergeConfig(result[key] || {}, value);
|
|
286
|
-
} else {
|
|
287
|
-
result[key] = value;
|
|
288
|
-
}
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
return result;
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
/**
|
|
295
|
-
* Validate configuration
|
|
296
|
-
* @private
|
|
297
|
-
*/
|
|
298
|
-
validateConfig(config) {
|
|
299
|
-
const errors = [];
|
|
300
|
-
|
|
301
|
-
// Validate system configuration
|
|
302
|
-
if (config.system) {
|
|
303
|
-
const { maxAgentsPerProject, defaultModel, stateDirectory } = config.system;
|
|
304
|
-
|
|
305
|
-
if (maxAgentsPerProject && (typeof maxAgentsPerProject !== 'number' || maxAgentsPerProject < 1)) {
|
|
306
|
-
errors.push('system.maxAgentsPerProject must be a positive number');
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
if (defaultModel && !Object.values(MODELS).includes(defaultModel)) {
|
|
310
|
-
errors.push(`system.defaultModel must be one of: ${Object.values(MODELS).join(', ')}`);
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
if (stateDirectory && typeof stateDirectory !== 'string') {
|
|
314
|
-
errors.push('system.stateDirectory must be a string');
|
|
315
|
-
}
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
// Validate backend configuration
|
|
319
|
-
if (config.backend) {
|
|
320
|
-
const { baseUrl, timeout, retryAttempts } = config.backend;
|
|
321
|
-
|
|
322
|
-
if (baseUrl && typeof baseUrl !== 'string') {
|
|
323
|
-
errors.push('backend.baseUrl must be a string');
|
|
324
|
-
}
|
|
325
|
-
|
|
326
|
-
if (timeout && (typeof timeout !== 'number' || timeout < 1000)) {
|
|
327
|
-
errors.push('backend.timeout must be a number >= 1000');
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
if (retryAttempts && (typeof retryAttempts !== 'number' || retryAttempts < 0)) {
|
|
331
|
-
errors.push('backend.retryAttempts must be a non-negative number');
|
|
332
|
-
}
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
// Validate tool configuration
|
|
336
|
-
if (config.tools) {
|
|
337
|
-
for (const [toolName, toolConfig] of Object.entries(config.tools)) {
|
|
338
|
-
if (toolConfig && typeof toolConfig !== 'object') {
|
|
339
|
-
errors.push(`tools.${toolName} must be an object`);
|
|
340
|
-
}
|
|
341
|
-
|
|
342
|
-
if (toolConfig?.timeout && (typeof toolConfig.timeout !== 'number' || toolConfig.timeout < 1000)) {
|
|
343
|
-
errors.push(`tools.${toolName}.timeout must be a number >= 1000`);
|
|
344
|
-
}
|
|
345
|
-
}
|
|
346
|
-
}
|
|
347
|
-
|
|
348
|
-
// Validate model routing
|
|
349
|
-
if (config.models?.routingTable) {
|
|
350
|
-
const routingTable = config.models.routingTable;
|
|
351
|
-
|
|
352
|
-
for (const [task, models] of Object.entries(routingTable)) {
|
|
353
|
-
if (!Array.isArray(models)) {
|
|
354
|
-
errors.push(`models.routingTable.${task} must be an array`);
|
|
355
|
-
continue;
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
for (const model of models) {
|
|
359
|
-
if (!Object.values(MODELS).includes(model)) {
|
|
360
|
-
errors.push(`Invalid model in routing table: ${model}`);
|
|
361
|
-
}
|
|
362
|
-
}
|
|
363
|
-
}
|
|
364
|
-
}
|
|
365
|
-
|
|
366
|
-
return {
|
|
367
|
-
valid: errors.length === 0,
|
|
368
|
-
errors
|
|
369
|
-
};
|
|
370
|
-
}
|
|
371
|
-
|
|
372
|
-
/**
|
|
373
|
-
* Transform configuration after loading
|
|
374
|
-
* @private
|
|
375
|
-
*/
|
|
376
|
-
transformConfig(config) {
|
|
377
|
-
// Ensure required nested objects exist
|
|
378
|
-
if (!config.system) config.system = {};
|
|
379
|
-
if (!config.backend) config.backend = {};
|
|
380
|
-
if (!config.tools) config.tools = {};
|
|
381
|
-
if (!config.models) config.models = {};
|
|
382
|
-
if (!config.context) config.context = {};
|
|
383
|
-
if (!config.logging) config.logging = {};
|
|
384
|
-
|
|
385
|
-
// Apply defaults for missing values
|
|
386
|
-
config.system.maxAgentsPerProject = config.system.maxAgentsPerProject || SYSTEM_DEFAULTS.MAX_AGENTS_PER_PROJECT;
|
|
387
|
-
config.system.defaultModel = config.system.defaultModel || SYSTEM_DEFAULTS.DEFAULT_MODEL;
|
|
388
|
-
config.system.stateDirectory = config.system.stateDirectory || SYSTEM_DEFAULTS.STATE_DIRECTORY;
|
|
389
|
-
config.system.maxPauseDuration = config.system.maxPauseDuration || SYSTEM_DEFAULTS.MAX_PAUSE_DURATION;
|
|
390
|
-
|
|
391
|
-
config.context.maxSize = config.context.maxSize || SYSTEM_DEFAULTS.MAX_CONTEXT_SIZE;
|
|
392
|
-
config.context.maxReferences = config.context.maxReferences || SYSTEM_DEFAULTS.MAX_CONTEXT_REFERENCES;
|
|
393
|
-
config.context.autoValidation = config.context.autoValidation !== false;
|
|
394
|
-
config.context.cacheExpiry = config.context.cacheExpiry || SYSTEM_DEFAULTS.CACHE_EXPIRY;
|
|
395
|
-
|
|
396
|
-
// Ensure model routing table exists
|
|
397
|
-
if (!config.models.routingTable) {
|
|
398
|
-
config.models.routingTable = { ...MODEL_ROUTING };
|
|
399
|
-
}
|
|
400
|
-
|
|
401
|
-
// Ensure essential tools are configured
|
|
402
|
-
for (const toolName of Object.values(TOOL_NAMES)) {
|
|
403
|
-
if (!config.tools[toolName]) {
|
|
404
|
-
config.tools[toolName] = {
|
|
405
|
-
enabled: true,
|
|
406
|
-
timeout: SYSTEM_DEFAULTS.MAX_TOOL_EXECUTION_TIME
|
|
407
|
-
};
|
|
408
|
-
}
|
|
409
|
-
}
|
|
410
|
-
|
|
411
|
-
return config;
|
|
412
|
-
}
|
|
413
|
-
|
|
414
|
-
/**
|
|
415
|
-
* Notify configuration change listeners
|
|
416
|
-
* @private
|
|
417
|
-
*/
|
|
418
|
-
notifyConfigChange(config) {
|
|
419
|
-
for (const listener of this.changeListeners) {
|
|
420
|
-
try {
|
|
421
|
-
listener(config);
|
|
422
|
-
} catch (error) {
|
|
423
|
-
console.error('Config change listener error:', error.message);
|
|
424
|
-
}
|
|
425
|
-
}
|
|
426
|
-
}
|
|
427
|
-
|
|
428
|
-
/**
|
|
429
|
-
* Get default configuration
|
|
430
|
-
* @private
|
|
431
|
-
*/
|
|
432
|
-
getDefaultConfig() {
|
|
433
|
-
return {
|
|
434
|
-
system: {
|
|
435
|
-
maxAgentsPerProject: SYSTEM_DEFAULTS.MAX_AGENTS_PER_PROJECT,
|
|
436
|
-
qualityInspectorInterval: SYSTEM_DEFAULTS.QUALITY_INSPECTOR_INTERVAL,
|
|
437
|
-
defaultModel: SYSTEM_DEFAULTS.DEFAULT_MODEL,
|
|
438
|
-
stateDirectory: SYSTEM_DEFAULTS.STATE_DIRECTORY,
|
|
439
|
-
maxPauseDuration: SYSTEM_DEFAULTS.MAX_PAUSE_DURATION
|
|
440
|
-
},
|
|
441
|
-
|
|
442
|
-
context: {
|
|
443
|
-
maxSize: SYSTEM_DEFAULTS.MAX_CONTEXT_SIZE,
|
|
444
|
-
maxReferences: SYSTEM_DEFAULTS.MAX_CONTEXT_REFERENCES,
|
|
445
|
-
autoValidation: true,
|
|
446
|
-
cacheExpiry: SYSTEM_DEFAULTS.CACHE_EXPIRY
|
|
447
|
-
},
|
|
448
|
-
|
|
449
|
-
models: {
|
|
450
|
-
routingTable: { ...MODEL_ROUTING }
|
|
451
|
-
},
|
|
452
|
-
|
|
453
|
-
tools: {
|
|
454
|
-
[TOOL_NAMES.TERMINAL]: {
|
|
455
|
-
timeout: 30000,
|
|
456
|
-
enabled: true
|
|
457
|
-
},
|
|
458
|
-
[TOOL_NAMES.FILESYSTEM]: {
|
|
459
|
-
maxFileSize: SYSTEM_DEFAULTS.MAX_FILE_SIZE,
|
|
460
|
-
enabled: true
|
|
461
|
-
},
|
|
462
|
-
[TOOL_NAMES.BROWSER]: {
|
|
463
|
-
timeout: 60000,
|
|
464
|
-
enabled: true
|
|
465
|
-
},
|
|
466
|
-
[TOOL_NAMES.AGENT_DELAY]: {
|
|
467
|
-
maxDuration: SYSTEM_DEFAULTS.MAX_PAUSE_DURATION,
|
|
468
|
-
enabled: true
|
|
469
|
-
}
|
|
470
|
-
},
|
|
471
|
-
|
|
472
|
-
backend: {
|
|
473
|
-
baseUrl: 'https://api.loxia.ai',
|
|
474
|
-
timeout: 60000,
|
|
475
|
-
retryAttempts: 3
|
|
476
|
-
},
|
|
477
|
-
|
|
478
|
-
budget: {
|
|
479
|
-
limit: 100.00,
|
|
480
|
-
alertThreshold: 0.8,
|
|
481
|
-
trackUsage: true
|
|
482
|
-
},
|
|
483
|
-
|
|
484
|
-
logging: {
|
|
485
|
-
level: 'info',
|
|
486
|
-
outputs: ['console'],
|
|
487
|
-
colors: true,
|
|
488
|
-
timestamp: true
|
|
489
|
-
},
|
|
490
|
-
|
|
491
|
-
interfaces: {
|
|
492
|
-
cli: {
|
|
493
|
-
enabled: true,
|
|
494
|
-
historySize: 1000
|
|
495
|
-
},
|
|
496
|
-
web: {
|
|
497
|
-
enabled: true,
|
|
498
|
-
port: 3000,
|
|
499
|
-
host: 'localhost'
|
|
500
|
-
},
|
|
501
|
-
vscode: {
|
|
502
|
-
enabled: true,
|
|
503
|
-
contextMenus: true,
|
|
504
|
-
statusBar: true
|
|
505
|
-
}
|
|
506
|
-
}
|
|
507
|
-
};
|
|
508
|
-
}
|
|
509
|
-
|
|
510
|
-
/**
|
|
511
|
-
* Export configuration to file
|
|
512
|
-
* @param {string} filePath - Target file path
|
|
513
|
-
* @param {Object} options - Export options
|
|
514
|
-
* @returns {Promise<void>}
|
|
515
|
-
*/
|
|
516
|
-
async exportConfig(filePath, options = {}) {
|
|
517
|
-
const config = options.includeDefaults ?
|
|
518
|
-
this.getConfig() :
|
|
519
|
-
this.getConfigWithoutDefaults();
|
|
520
|
-
|
|
521
|
-
const ext = path.extname(filePath).toLowerCase();
|
|
522
|
-
let content;
|
|
523
|
-
|
|
524
|
-
switch (ext) {
|
|
525
|
-
case '.json':
|
|
526
|
-
content = JSON.stringify(config, null, 2);
|
|
527
|
-
break;
|
|
528
|
-
|
|
529
|
-
case '.js':
|
|
530
|
-
content = `module.exports = ${JSON.stringify(config, null, 2)};`;
|
|
531
|
-
break;
|
|
532
|
-
|
|
533
|
-
default:
|
|
534
|
-
throw new Error(`Unsupported export format: ${ext}`);
|
|
535
|
-
}
|
|
536
|
-
|
|
537
|
-
await fs.writeFile(filePath, content, 'utf8');
|
|
538
|
-
}
|
|
539
|
-
|
|
540
|
-
/**
|
|
541
|
-
* Get configuration without default values
|
|
542
|
-
* @private
|
|
543
|
-
*/
|
|
544
|
-
getConfigWithoutDefaults() {
|
|
545
|
-
// This would return only explicitly set values
|
|
546
|
-
// For now, return the full config
|
|
547
|
-
return this.getConfig();
|
|
548
|
-
}
|
|
549
|
-
|
|
550
|
-
/**
|
|
551
|
-
* Reset configuration to defaults
|
|
552
|
-
*/
|
|
553
|
-
resetToDefaults() {
|
|
554
|
-
this.config = { ...this.defaultConfig };
|
|
555
|
-
this.notifyConfigChange(this.config);
|
|
556
|
-
}
|
|
557
|
-
|
|
558
|
-
/**
|
|
559
|
-
* Cleanup resources
|
|
560
|
-
*/
|
|
561
|
-
cleanup() {
|
|
562
|
-
// Stop watching files
|
|
563
|
-
for (const watcher of this.watchers.values()) {
|
|
564
|
-
watcher.close();
|
|
565
|
-
}
|
|
566
|
-
this.watchers.clear();
|
|
567
|
-
|
|
568
|
-
// Clear listeners
|
|
569
|
-
this.changeListeners.clear();
|
|
570
|
-
}
|
|
571
|
-
}
|
|
572
|
-
|
|
573
|
-
/**
|
|
574
|
-
* Create a configuration manager instance
|
|
575
|
-
* @param {Object} options - Configuration options
|
|
576
|
-
* @returns {ConfigManager} ConfigManager instance
|
|
577
|
-
*/
|
|
578
|
-
function createConfigManager(options = {}) {
|
|
579
|
-
return new ConfigManager(options);
|
|
580
|
-
}
|
|
581
|
-
|
|
582
|
-
export { ConfigManager, createConfigManager };
|
|
1
|
+
const a0_0x1fa326=a0_0x1ddc;function a0_0x18ca(){const _0x19c364=['rMfPBgvKihrVihjLBg9HzcbJB25MAwCGywz0zxiGy2HHBMDLigLUia','zxH0BMfTzq','DMfSDwvZ','tufyx1rpt0XFrvHfq1vusu9ox1rjtuu','Dg9VBhm','C3rYAw5N','zw52uhjLzML4','lNrPBwvVDxqGBxvZDcbIzsbHig51BwjLCIa+psaXmdaW','zgvMyxvSDe1VzgvS','mJq3n2fwEw90Ea','Bg9HzenVBMzPzW','Bg9Nz2LUzY5SzxzLBa','mteWnZK3nMvVr2fXAq','z2v0','zgvMyxvSDa','C3LZDgvTlNn0yxrLrgLYzwn0B3j5ig11C3qGyMuGysbZDhjPBMC','ChvZAa','CMvHzezPBgu','ig11C3qGyMuGyw4GyxjYyxK','D2f0y2HdB25MAwC','zgvSzxrL','Cg9W','zw50CMLLCW','yxv0B1zHBgLKyxrPB24','mtGXmZaYm21tAM5czW','C3rYAw5NAwz5','AM9PBG','CMvZB2X2zq','revgqvvmvf9nt0rfta','lMPZB24','Dg9VBhmU','y29UzMLN','BwvZC2fNzq','D3jPDgvgAwXL','oti5odK1wNfHu2rq','x1rpt0Xtx0voqujmruq','lNLHBwW','C2v0','Bg9JywXOB3n0','yMfJA2vUza','Aw5MBW','lNLTBa','ndbetvHsCxK','CgfYC2vfBNzwywX1zq','te9ysue','C3LZDgvTlM1HEefNzw50C1bLCLbYB2PLy3q','DMfSAwrHDgvdB25MAwC','C3LZDgvT','D2fYBG','nta3nJaWzgf2yNjL','z2v0rgvMyxvSDenVBMzPzW','mZm0vhnHqwPj','tufyx0nptLrfwfrFu0LArq','Bw9KzwXZ','tufyx0nptLrfwfrFuKvgrvjftKnfuW','u1rbvevFreLsrunut1jz','vw5ZDxbWB3j0zwqGzxHWB3j0igzVCM1HDdOG','vw5ZDxbWB3j0zwqGy29UzMLNDxjHDgLVBIbMAwXLigzVCM1HDdOG','y2XLyxi','tufyx0fhru5uu19qrvjFufjpsKvdva','Bg9HzenVBMzPz0zPBgu','CgfYC2u','x0rfrKfvtfrFtu9eruW','x1nuqvrfx0rjuG','tufyx1bbvvnfx0rvuKfusu9o','mZiWotCWDezXshDb','x0jbq0TftKrFveLnru9vva','qLjpv1nfuG','z2v0q29UzMLN','DMfSAwq','AgfZ','y2HHBMDLtgLZDgvUzxjZ','C3bSAxq','Aw5JBhvKzxm','y2fJAgvfEhbPCNK','mZbqrK1tC3O','lMPZ','rKLmrvnzu1rftq','nZu0mZC2q3rorefL','Bwf4uMvMzxjLBMnLCW','rMfPBgvKihrVigXVywqGy29UzMLNigzPBguG','ywrKq2HHBMDLtgLZDgvUzxi','yMfJA2vUzc5IyxnLvxjS','y29UzMLNugf0Ahm','Bwf4qwDLBNrZugvYuhjVAMvJDa','BwvYz2vdB25MAwC','wufntcbJB25MAwD1CMf0Aw9UigzPBgvZig5VDcbZDxbWB3j0zwqGAw4GDgHPCYbPBxbSzw1LBNrHDgLVBG','Dg9mB3DLCKnHC2u','y29UDgv4Da','B2jQzwn0','D2f0y2HLCNm','BNvTyMvY','Bwf4ugf1C2veDxjHDgLVBG','y2XVC2u','zgvMyxvSDenVBMzPzW','q0fdsevFrvHqsvjz','BM90Awz5q29UzMLNq2HHBMDL','yxbPs2v5','CM91DgLUz1rHyMXL','yMfJA2vUzc5IyxnLvxjSig11C3qGyMuGysbZDhjPBMC'];a0_0x18ca=function(){return _0x19c364;};return a0_0x18ca();}(function(_0x4ea9fb,_0x5220a4){const _0x27e39c=a0_0x1ddc,_0x63610b=_0x4ea9fb();while(!![]){try{const _0x1afd50=parseInt(_0x27e39c(0x1d3))/0x1*(-parseInt(_0x27e39c(0x199))/0x2)+-parseInt(_0x27e39c(0x1ec))/0x3+parseInt(_0x27e39c(0x1d6))/0x4+parseInt(_0x27e39c(0x1a7))/0x5*(-parseInt(_0x27e39c(0x1b1))/0x6)+parseInt(_0x27e39c(0x1b4))/0x7+parseInt(_0x27e39c(0x197))/0x8+parseInt(_0x27e39c(0x1e2))/0x9*(parseInt(_0x27e39c(0x1f4))/0xa);if(_0x1afd50===_0x5220a4)break;else _0x63610b['push'](_0x63610b['shift']());}catch(_0x3d91bc){_0x63610b['push'](_0x63610b['shift']());}}}(a0_0x18ca,0x331fe));import{promises as a0_0x15f482}from'fs';import a0_0x483540 from'path';import{SYSTEM_DEFAULTS,MODELS,MODEL_ROUTING,TOOL_NAMES,STATE_DIRECTORIES,ERROR_TYPES}from'./constants.js';class ConfigManager{constructor(_0x3e7e5a={}){const _0x206af2=a0_0x1ddc;this['configPaths']=_0x3e7e5a[_0x206af2(0x1b9)]||[],this['envPrefix']=_0x3e7e5a[_0x206af2(0x1d0)]||_0x206af2(0x1f6),this[_0x206af2(0x1e9)]={},this['watchers']=new Map(),this['changeListeners']=new Set(),this[_0x206af2(0x1c4)]=this['getDefaultConfig']();}async[a0_0x1fa326(0x1d4)](){const _0x4ff2a8=a0_0x1fa326;let _0x33033e={...this[_0x4ff2a8(0x1c4)]};for(const _0x1e06e1 of this[_0x4ff2a8(0x1b9)]){try{const _0x24dac8=await this[_0x4ff2a8(0x1a2)](_0x1e06e1);_0x33033e=this[_0x4ff2a8(0x1bb)](_0x33033e,_0x24dac8);}catch(_0x791514){console['warn'](_0x4ff2a8(0x1b6)+_0x1e06e1+':',_0x791514[_0x4ff2a8(0x1ea)]);}}const _0x402de7=this['loadEnvironmentConfig']();_0x33033e=this['mergeConfig'](_0x33033e,_0x402de7);const _0x54b20f=this[_0x4ff2a8(0x1f8)](_0x33033e);if(!_0x54b20f[_0x4ff2a8(0x1ab)])throw new Error('Configuration\x20validation\x20failed:\x20'+_0x54b20f['errors'][_0x4ff2a8(0x1e4)](',\x20'));return _0x33033e=this['transformConfig'](_0x33033e),this['config']=_0x33033e,this['notifyConfigChange'](_0x33033e),_0x33033e;}['getConfig'](){const _0x387271=a0_0x1fa326;return{...this[_0x387271(0x1e9)]};}[a0_0x1fa326(0x1d7)](_0x1c1f5a,defaultValue=undefined){const _0x55cd8a=a0_0x1fa326,_0x5d7a8e=_0x1c1f5a['split']('.');let _0x463b3e=this['config'];for(const _0x32ff24 of _0x5d7a8e){if(_0x463b3e&&typeof _0x463b3e===_0x55cd8a(0x1bf)&&_0x32ff24 in _0x463b3e)_0x463b3e=_0x463b3e[_0x32ff24];else return defaultValue;}return _0x463b3e;}['set'](_0x41e529,_0x4744b5){const _0x1ced86=a0_0x1fa326,_0x12794b=_0x41e529['split']('.'),_0x464e52=_0x12794b[_0x1ced86(0x1df)]();let _0xa5a96b=this[_0x1ced86(0x1e9)];for(const _0x4f0cd2 of _0x12794b){(!(_0x4f0cd2 in _0xa5a96b)||typeof _0xa5a96b[_0x4f0cd2]!==_0x1ced86(0x1bf))&&(_0xa5a96b[_0x4f0cd2]={}),_0xa5a96b=_0xa5a96b[_0x4f0cd2];}_0xa5a96b[_0x464e52]=_0x4744b5,this['notifyConfigChange'](this[_0x1ced86(0x1e9)]);}async[a0_0x1fa326(0x1dd)](_0x3fcd8c=!![]){const _0x10f221=a0_0x1fa326;if(!_0x3fcd8c){for(const [_0x2d601d,_0x3062e3]of this[_0x10f221(0x1c0)]){_0x3062e3[_0x10f221(0x1c3)](),this['watchers']['delete'](_0x2d601d);}return;}for(const _0x55e97e of this[_0x10f221(0x1b9)]){if(this[_0x10f221(0x1c0)][_0x10f221(0x1ac)](_0x55e97e))continue;try{const {watch:_0x5cf10a}=await import('fs'),_0x7a5aa6=_0x5cf10a(_0x55e97e,async _0x3da92b=>{const _0x13a3dc=_0x10f221;if(_0x3da92b==='change')try{await this[_0x13a3dc(0x1d4)]();}catch(_0x35e2bf){console['error'](_0x13a3dc(0x1ca)+_0x55e97e+':',_0x35e2bf['message']);}});this['watchers'][_0x10f221(0x1ef)](_0x55e97e,_0x7a5aa6);}catch(_0x4af2e7){console[_0x10f221(0x196)]('Failed\x20to\x20watch\x20config\x20file\x20'+_0x55e97e+':',_0x4af2e7['message']);}}}[a0_0x1fa326(0x1b7)](_0x58fed1){this['changeListeners']['add'](_0x58fed1);}['removeChangeListener'](_0x34fab5){const _0x4b61c0=a0_0x1fa326;this[_0x4b61c0(0x1ad)][_0x4b61c0(0x1de)](_0x34fab5);}async['loadConfigFile'](_0x279a47){const _0x5d14ca=a0_0x1fa326;try{const _0xee18b5=await a0_0x15f482[_0x5d14ca(0x1db)](_0x279a47,'utf8'),_0x5d0d30=a0_0x483540[_0x5d14ca(0x1cb)](_0x279a47)[_0x5d14ca(0x1bd)]();switch(_0x5d0d30){case _0x5d14ca(0x1e7):return JSON[_0x5d14ca(0x1a3)](_0xee18b5);case _0x5d14ca(0x1b2):const _0x1686b6=a0_0x483540[_0x5d14ca(0x1e5)](_0x279a47),module=await import(_0x1686b6);return module[_0x5d14ca(0x1d8)]||module;case _0x5d14ca(0x1ee):case _0x5d14ca(0x1f3):throw new Error(_0x5d14ca(0x1bc));default:throw new Error(_0x5d14ca(0x19f)+_0x5d0d30);}}catch(_0x21c21f){throw new Error('Failed\x20to\x20load\x20config\x20file\x20'+_0x279a47+':\x20'+_0x21c21f[_0x5d14ca(0x1ea)]);}}['loadEnvironmentConfig'](){const _0x3cef5e=a0_0x1fa326,_0x4daf3c={},_0x584ab5={[this['envPrefix']+'_API_KEY']:_0x3cef5e(0x1c7),[this['envPrefix']+'_LOG_LEVEL']:_0x3cef5e(0x1d5),[this[_0x3cef5e(0x1d0)]+'_MAX_AGENTS']:_0x3cef5e(0x1f7),[this[_0x3cef5e(0x1d0)]+_0x3cef5e(0x1a4)]:'system.defaultModel',[this['envPrefix']+'_BACKEND_URL']:_0x3cef5e(0x1b8),[this[_0x3cef5e(0x1d0)]+_0x3cef5e(0x1a8)]:'backend.timeout',[this['envPrefix']+_0x3cef5e(0x1a5)]:'system.stateDirectory',[this['envPrefix']+'_BUDGET_LIMIT']:'budget.limit',[this['envPrefix']+_0x3cef5e(0x1ed)]:'tools.enabled'};for(const [_0x4df6f6,_0x2a619f]of Object[_0x3cef5e(0x1e0)](_0x584ab5)){const _0x3c5c28=process['env'][_0x4df6f6];_0x3c5c28!==undefined&&this['setNestedValue'](_0x4daf3c,_0x2a619f,this['parseEnvValue'](_0x3c5c28));}return _0x4daf3c;}[a0_0x1fa326(0x1f5)](_0x4b9abc){const _0x518492=a0_0x1fa326;try{return JSON[_0x518492(0x1a3)](_0x4b9abc);}catch{return _0x4b9abc;}}['setNestedValue'](_0xf4fb75,_0x7ee5b8,_0x43f3de){const _0x55eefd=a0_0x1fa326,_0x479a98=_0x7ee5b8[_0x55eefd(0x1ae)]('.'),_0x42db1b=_0x479a98['pop']();let _0x5e20d2=_0xf4fb75;for(const _0x1a7053 of _0x479a98){!(_0x1a7053 in _0x5e20d2)&&(_0x5e20d2[_0x1a7053]={}),_0x5e20d2=_0x5e20d2[_0x1a7053];}_0x5e20d2[_0x42db1b]=_0x43f3de;}['mergeConfig'](_0xf6169b,_0x30619f){const _0x379151=a0_0x1fa326,_0xfd9d13={..._0xf6169b};for(const [_0x1ebbc7,_0x38338b]of Object[_0x379151(0x1e0)](_0x30619f)){_0x38338b&&typeof _0x38338b===_0x379151(0x1bf)&&!Array['isArray'](_0x38338b)?_0xfd9d13[_0x1ebbc7]=this[_0x379151(0x1bb)](_0xfd9d13[_0x1ebbc7]||{},_0x38338b):_0xfd9d13[_0x1ebbc7]=_0x38338b;}return _0xfd9d13;}['validateConfig'](_0x1d28bb){const _0x1b0436=a0_0x1fa326,_0x278a22=[];if(_0x1d28bb['system']){const {maxAgentsPerProject:_0x39ffa5,defaultModel:defaultModel,stateDirectory:_0x44e46f}=_0x1d28bb['system'];_0x39ffa5&&(typeof _0x39ffa5!=='number'||_0x39ffa5<0x1)&&_0x278a22['push']('system.maxAgentsPerProject\x20must\x20be\x20a\x20positive\x20number'),defaultModel&&!Object[_0x1b0436(0x1cc)](MODELS)['includes'](defaultModel)&&_0x278a22['push']('system.defaultModel\x20must\x20be\x20one\x20of:\x20'+Object[_0x1b0436(0x1cc)](MODELS)['join'](',\x20')),_0x44e46f&&typeof _0x44e46f!=='string'&&_0x278a22['push'](_0x1b0436(0x1d9));}if(_0x1d28bb[_0x1b0436(0x1f1)]){const {baseUrl:_0x580b30,timeout:_0x2c9c6d,retryAttempts:_0x35d3c6}=_0x1d28bb[_0x1b0436(0x1f1)];_0x580b30&&typeof _0x580b30!==_0x1b0436(0x1cf)&&_0x278a22[_0x1b0436(0x1da)](_0x1b0436(0x1c9)),_0x2c9c6d&&(typeof _0x2c9c6d!==_0x1b0436(0x1c1)||_0x2c9c6d<0x3e8)&&_0x278a22['push']('backend.timeout\x20must\x20be\x20a\x20number\x20>=\x201000'),_0x35d3c6&&(typeof _0x35d3c6!==_0x1b0436(0x1c1)||_0x35d3c6<0x0)&&_0x278a22['push']('backend.retryAttempts\x20must\x20be\x20a\x20non-negative\x20number');}if(_0x1d28bb[_0x1b0436(0x1ce)])for(const [_0x11c539,_0x290869]of Object[_0x1b0436(0x1e0)](_0x1d28bb[_0x1b0436(0x1ce)])){_0x290869&&typeof _0x290869!=='object'&&_0x278a22[_0x1b0436(0x1da)](_0x1b0436(0x1e8)+_0x11c539+'\x20must\x20be\x20an\x20object'),_0x290869?.['timeout']&&(typeof _0x290869['timeout']!=='number'||_0x290869['timeout']<0x3e8)&&_0x278a22[_0x1b0436(0x1da)]('tools.'+_0x11c539+_0x1b0436(0x1d1));}if(_0x1d28bb[_0x1b0436(0x19b)]?.['routingTable']){const _0x2edb48=_0x1d28bb[_0x1b0436(0x19b)][_0x1b0436(0x1c8)];for(const [_0xdd2a66,_0x16ccbe]of Object['entries'](_0x2edb48)){if(!Array['isArray'](_0x16ccbe)){_0x278a22['push']('models.routingTable.'+_0xdd2a66+_0x1b0436(0x1dc));continue;}for(const _0x45b6e4 of _0x16ccbe){!Object[_0x1b0436(0x1cc)](MODELS)[_0x1b0436(0x1af)](_0x45b6e4)&&_0x278a22[_0x1b0436(0x1da)]('Invalid\x20model\x20in\x20routing\x20table:\x20'+_0x45b6e4);}}}return{'valid':_0x278a22['length']===0x0,'errors':_0x278a22};}['transformConfig'](_0x31226a){const _0x360480=a0_0x1fa326;if(!_0x31226a[_0x360480(0x195)])_0x31226a['system']={};if(!_0x31226a['backend'])_0x31226a['backend']={};if(!_0x31226a['tools'])_0x31226a[_0x360480(0x1ce)]={};if(!_0x31226a['models'])_0x31226a[_0x360480(0x19b)]={};if(!_0x31226a['context'])_0x31226a[_0x360480(0x1be)]={};if(!_0x31226a['logging'])_0x31226a['logging']={};_0x31226a['system'][_0x360480(0x1ba)]=_0x31226a['system'][_0x360480(0x1ba)]||SYSTEM_DEFAULTS[_0x360480(0x1a1)],_0x31226a[_0x360480(0x195)][_0x360480(0x1d2)]=_0x31226a[_0x360480(0x195)]['defaultModel']||SYSTEM_DEFAULTS[_0x360480(0x1e6)],_0x31226a[_0x360480(0x195)]['stateDirectory']=_0x31226a['system']['stateDirectory']||SYSTEM_DEFAULTS[_0x360480(0x19d)],_0x31226a['system']['maxPauseDuration']=_0x31226a['system'][_0x360480(0x1c2)]||SYSTEM_DEFAULTS[_0x360480(0x1a6)],_0x31226a['context']['maxSize']=_0x31226a[_0x360480(0x1be)]['maxSize']||SYSTEM_DEFAULTS[_0x360480(0x19a)],_0x31226a[_0x360480(0x1be)]['maxReferences']=_0x31226a[_0x360480(0x1be)][_0x360480(0x1b5)]||SYSTEM_DEFAULTS['MAX_CONTEXT_REFERENCES'],_0x31226a['context'][_0x360480(0x1e1)]=_0x31226a[_0x360480(0x1be)]['autoValidation']!==![],_0x31226a['context'][_0x360480(0x1b0)]=_0x31226a[_0x360480(0x1be)]['cacheExpiry']||SYSTEM_DEFAULTS[_0x360480(0x1c5)];!_0x31226a[_0x360480(0x19b)][_0x360480(0x1c8)]&&(_0x31226a[_0x360480(0x19b)]['routingTable']={...MODEL_ROUTING});for(const _0x40de58 of Object[_0x360480(0x1cc)](TOOL_NAMES)){!_0x31226a[_0x360480(0x1ce)][_0x40de58]&&(_0x31226a['tools'][_0x40de58]={'enabled':!![],'timeout':SYSTEM_DEFAULTS[_0x360480(0x1cd)]});}return _0x31226a;}[a0_0x1fa326(0x1c6)](_0x684f5c){const _0x496866=a0_0x1fa326;for(const _0x1dcb88 of this[_0x496866(0x1ad)]){try{_0x1dcb88(_0x684f5c);}catch(_0x33429c){console['error']('Config\x20change\x20listener\x20error:',_0x33429c['message']);}}}[a0_0x1fa326(0x198)](){const _0x5c42a8=a0_0x1fa326;return{'system':{'maxAgentsPerProject':SYSTEM_DEFAULTS['MAX_AGENTS_PER_PROJECT'],'qualityInspectorInterval':SYSTEM_DEFAULTS['QUALITY_INSPECTOR_INTERVAL'],'defaultModel':SYSTEM_DEFAULTS['DEFAULT_MODEL'],'stateDirectory':SYSTEM_DEFAULTS[_0x5c42a8(0x19d)],'maxPauseDuration':SYSTEM_DEFAULTS[_0x5c42a8(0x1a6)]},'context':{'maxSize':SYSTEM_DEFAULTS[_0x5c42a8(0x19a)],'maxReferences':SYSTEM_DEFAULTS[_0x5c42a8(0x19c)],'autoValidation':!![],'cacheExpiry':SYSTEM_DEFAULTS[_0x5c42a8(0x1c5)]},'models':{'routingTable':{...MODEL_ROUTING}},'tools':{[TOOL_NAMES['TERMINAL']]:{'timeout':0x7530,'enabled':!![]},[TOOL_NAMES[_0x5c42a8(0x1b3)]]:{'maxFileSize':SYSTEM_DEFAULTS['MAX_FILE_SIZE'],'enabled':!![]},[TOOL_NAMES[_0x5c42a8(0x1a9)]]:{'timeout':0xea60,'enabled':!![]},[TOOL_NAMES['AGENT_DELAY']]:{'maxDuration':SYSTEM_DEFAULTS['MAX_PAUSE_DURATION'],'enabled':!![]}},'backend':{'baseUrl':'https://api.loxia.ai','timeout':0xea60,'retryAttempts':0x3},'budget':{'limit':0x64,'alertThreshold':0.8,'trackUsage':!![]},'logging':{'level':_0x5c42a8(0x1f2),'outputs':['console'],'colors':!![],'timestamp':!![]},'interfaces':{'cli':{'enabled':!![],'historySize':0x3e8},'web':{'enabled':!![],'port':0xbb8,'host':_0x5c42a8(0x1f0)},'vscode':{'enabled':!![],'contextMenus':!![],'statusBar':!![]}}};}async['exportConfig'](_0x36880c,_0x48e0a8={}){const _0x305603=a0_0x1fa326,_0x1eded8=_0x48e0a8['includeDefaults']?this[_0x305603(0x1aa)]():this['getConfigWithoutDefaults'](),_0x437876=a0_0x483540['extname'](_0x36880c)[_0x305603(0x1bd)]();let _0x2c7667;switch(_0x437876){case'.json':_0x2c7667=JSON[_0x305603(0x1e3)](_0x1eded8,null,0x2);break;case _0x305603(0x1b2):_0x2c7667='module.exports\x20=\x20'+JSON['stringify'](_0x1eded8,null,0x2)+';';break;default:throw new Error(_0x305603(0x19e)+_0x437876);}await a0_0x15f482[_0x305603(0x1eb)](_0x36880c,_0x2c7667,'utf8');}['getConfigWithoutDefaults'](){return this['getConfig']();}['resetToDefaults'](){const _0x1fe97b=a0_0x1fa326;this['config']={...this[_0x1fe97b(0x1c4)]},this[_0x1fe97b(0x1c6)](this[_0x1fe97b(0x1e9)]);}['cleanup'](){const _0x14ee75=a0_0x1fa326;for(const _0x3e8dfb of this['watchers'][_0x14ee75(0x1cc)]()){_0x3e8dfb['close']();}this['watchers']['clear'](),this['changeListeners'][_0x14ee75(0x1a0)]();}}function createConfigManager(_0x315014={}){return new ConfigManager(_0x315014);}function a0_0x1ddc(_0xf90b00,_0x507419){_0xf90b00=_0xf90b00-0x195;const _0x18ca00=a0_0x18ca();let _0x1ddc9a=_0x18ca00[_0xf90b00];if(a0_0x1ddc['oxDRPp']===undefined){var _0x18cd0=function(_0x37ae36){const _0x14499e='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';let _0x15f482='',_0x483540='';for(let _0x3e7e5a=0x0,_0x33033e,_0x402de7,_0x54b20f=0x0;_0x402de7=_0x37ae36['charAt'](_0x54b20f++);~_0x402de7&&(_0x33033e=_0x3e7e5a%0x4?_0x33033e*0x40+_0x402de7:_0x402de7,_0x3e7e5a++%0x4)?_0x15f482+=String['fromCharCode'](0xff&_0x33033e>>(-0x2*_0x3e7e5a&0x6)):0x0){_0x402de7=_0x14499e['indexOf'](_0x402de7);}for(let _0x1e06e1=0x0,_0x24dac8=_0x15f482['length'];_0x1e06e1<_0x24dac8;_0x1e06e1++){_0x483540+='%'+('00'+_0x15f482['charCodeAt'](_0x1e06e1)['toString'](0x10))['slice'](-0x2);}return decodeURIComponent(_0x483540);};a0_0x1ddc['BUpMTK']=_0x18cd0,a0_0x1ddc['qqWFis']={},a0_0x1ddc['oxDRPp']=!![];}const _0x1c9d77=_0x18ca00[0x0],_0x3a3569=_0xf90b00+_0x1c9d77,_0x2f3a3a=a0_0x1ddc['qqWFis'][_0x3a3569];return!_0x2f3a3a?(_0x1ddc9a=a0_0x1ddc['BUpMTK'](_0x1ddc9a),a0_0x1ddc['qqWFis'][_0x3a3569]=_0x1ddc9a):_0x1ddc9a=_0x2f3a3a,_0x1ddc9a;}export{ConfigManager,createConfigManager};
|