@loxia-labs/loxia-autopilot-one 1.0.1 → 1.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +44 -54
- package/bin/cli.js +1 -115
- package/bin/loxia-terminal-v2.js +3 -0
- package/bin/loxia-terminal.js +3 -0
- package/bin/start-with-terminal.js +3 -0
- package/package.json +15 -15
- package/scripts/install-scanners.js +1 -235
- package/src/analyzers/CSSAnalyzer.js +1 -297
- package/src/analyzers/ConfigValidator.js +1 -690
- package/src/analyzers/ESLintAnalyzer.js +1 -320
- package/src/analyzers/JavaScriptAnalyzer.js +1 -261
- package/src/analyzers/PrettierFormatter.js +1 -247
- package/src/analyzers/PythonAnalyzer.js +1 -266
- package/src/analyzers/SecurityAnalyzer.js +1 -729
- package/src/analyzers/TypeScriptAnalyzer.js +1 -247
- package/src/analyzers/codeCloneDetector/analyzer.js +1 -344
- package/src/analyzers/codeCloneDetector/detector.js +1 -203
- package/src/analyzers/codeCloneDetector/index.js +1 -160
- package/src/analyzers/codeCloneDetector/parser.js +1 -199
- package/src/analyzers/codeCloneDetector/reporter.js +1 -148
- package/src/analyzers/codeCloneDetector/scanner.js +1 -59
- package/src/core/agentPool.js +1 -1474
- package/src/core/agentScheduler.js +1 -2147
- package/src/core/contextManager.js +1 -709
- package/src/core/messageProcessor.js +1 -732
- package/src/core/orchestrator.js +1 -548
- package/src/core/stateManager.js +1 -877
- package/src/index.js +1 -631
- package/src/interfaces/cli.js +1 -549
- package/src/interfaces/terminal/__tests__/smoke/advancedFeatures.test.js +1 -0
- package/src/interfaces/terminal/__tests__/smoke/agentControl.test.js +1 -0
- package/src/interfaces/terminal/__tests__/smoke/agents.test.js +1 -0
- package/src/interfaces/terminal/__tests__/smoke/components.test.js +1 -0
- package/src/interfaces/terminal/__tests__/smoke/connection.test.js +1 -0
- package/src/interfaces/terminal/__tests__/smoke/enhancements.test.js +1 -0
- package/src/interfaces/terminal/__tests__/smoke/imports.test.js +1 -0
- package/src/interfaces/terminal/__tests__/smoke/messages.test.js +1 -0
- package/src/interfaces/terminal/__tests__/smoke/tools.test.js +1 -0
- package/src/interfaces/terminal/api/apiClient.js +1 -0
- package/src/interfaces/terminal/api/messageRouter.js +1 -0
- package/src/interfaces/terminal/api/session.js +1 -0
- package/src/interfaces/terminal/api/websocket.js +1 -0
- package/src/interfaces/terminal/components/AgentCreator.js +1 -0
- package/src/interfaces/terminal/components/AgentEditor.js +1 -0
- package/src/interfaces/terminal/components/AgentSwitcher.js +1 -0
- package/src/interfaces/terminal/components/ErrorBoundary.js +1 -0
- package/src/interfaces/terminal/components/ErrorPanel.js +1 -0
- package/src/interfaces/terminal/components/Header.js +1 -0
- package/src/interfaces/terminal/components/HelpPanel.js +1 -0
- package/src/interfaces/terminal/components/InputBox.js +1 -0
- package/src/interfaces/terminal/components/Layout.js +1 -0
- package/src/interfaces/terminal/components/LoadingSpinner.js +1 -0
- package/src/interfaces/terminal/components/MessageList.js +1 -0
- package/src/interfaces/terminal/components/MultilineTextInput.js +1 -0
- package/src/interfaces/terminal/components/SearchPanel.js +1 -0
- package/src/interfaces/terminal/components/SettingsPanel.js +1 -0
- package/src/interfaces/terminal/components/StatusBar.js +1 -0
- package/src/interfaces/terminal/components/TextInput.js +1 -0
- package/src/interfaces/terminal/config/agentEditorConstants.js +1 -0
- package/src/interfaces/terminal/config/constants.js +1 -0
- package/src/interfaces/terminal/index.js +1 -0
- package/src/interfaces/terminal/state/useAgentControl.js +1 -0
- package/src/interfaces/terminal/state/useAgents.js +1 -0
- package/src/interfaces/terminal/state/useConnection.js +1 -0
- package/src/interfaces/terminal/state/useMessages.js +1 -0
- package/src/interfaces/terminal/state/useTools.js +1 -0
- package/src/interfaces/terminal/utils/debugLogger.js +1 -0
- package/src/interfaces/terminal/utils/settingsStorage.js +1 -0
- package/src/interfaces/terminal/utils/theme.js +1 -0
- package/src/interfaces/webServer.js +1 -2162
- package/src/modules/fileExplorer/controller.js +1 -280
- package/src/modules/fileExplorer/index.js +1 -37
- package/src/modules/fileExplorer/middleware.js +1 -92
- package/src/modules/fileExplorer/routes.js +1 -125
- package/src/modules/fileExplorer/types.js +1 -44
- package/src/services/aiService.js +1 -1232
- package/src/services/apiKeyManager.js +1 -164
- package/src/services/benchmarkService.js +1 -366
- package/src/services/budgetService.js +1 -539
- package/src/services/contextInjectionService.js +1 -247
- package/src/services/conversationCompactionService.js +1 -637
- package/src/services/errorHandler.js +1 -810
- package/src/services/fileAttachmentService.js +1 -544
- package/src/services/modelRouterService.js +1 -366
- package/src/services/modelsService.js +1 -322
- package/src/services/qualityInspector.js +1 -796
- package/src/services/tokenCountingService.js +1 -536
- package/src/tools/agentCommunicationTool.js +1 -1344
- package/src/tools/agentDelayTool.js +1 -485
- package/src/tools/asyncToolManager.js +1 -604
- package/src/tools/baseTool.js +1 -800
- package/src/tools/browserTool.js +1 -920
- package/src/tools/cloneDetectionTool.js +1 -621
- package/src/tools/dependencyResolverTool.js +1 -1215
- package/src/tools/fileContentReplaceTool.js +1 -875
- package/src/tools/fileSystemTool.js +1 -1107
- package/src/tools/fileTreeTool.js +1 -853
- package/src/tools/imageTool.js +1 -901
- package/src/tools/importAnalyzerTool.js +1 -1060
- package/src/tools/jobDoneTool.js +1 -248
- package/src/tools/seekTool.js +1 -956
- package/src/tools/staticAnalysisTool.js +1 -1778
- package/src/tools/taskManagerTool.js +1 -2873
- package/src/tools/terminalTool.js +1 -2304
- package/src/tools/webTool.js +1 -1430
- package/src/types/agent.js +1 -519
- package/src/types/contextReference.js +1 -972
- package/src/types/conversation.js +1 -730
- package/src/types/toolCommand.js +1 -747
- package/src/utilities/attachmentValidator.js +1 -292
- package/src/utilities/configManager.js +1 -582
- package/src/utilities/constants.js +1 -722
- package/src/utilities/directoryAccessManager.js +1 -535
- package/src/utilities/fileProcessor.js +1 -307
- package/src/utilities/logger.js +1 -436
- package/src/utilities/tagParser.js +1 -1246
- package/src/utilities/toolConstants.js +1 -317
- package/web-ui/build/index.html +2 -2
- package/web-ui/build/static/{index-Dy2bYbOa.css → index-CClD1090.css} +1 -1
- package/web-ui/build/static/{index-CjkkcnFA.js → index-lCBai6dX.js} +66 -67
|
@@ -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
|
+
function a0_0x289e(){const _0x36a075=['Dg9VBhmUzw5HyMXLza','CMvTB3zLq2HHBMDLtgLZDgvUzxi','yMfJA2vUzc5IyxnLvxjS','y2XVC2u','yMfJA2vUzc50Aw1LB3v0','DMfSAwrHDgvdB25MAwC','C2v0tMvZDgvKvMfSDwu','Bwf4qwDLBNrZugvYuhjVAMvJDa','lMPZ','zw52uhjLzML4','tufyx1bbvvnfx0rvuKfusu9o','C3bSAxq','x0Xpr19mrvzfta','Aw5JBhvKzxm','x1rpt0Xtx0voqujmruq','ChvZAa','C3LZDgvTlMrLzMf1BhrnB2rLBcbTDxn0igjLig9UzsbVzJOG','BwvZC2fNzq','yxv0B1zHBgLKyxrPB24','nduXmJH1BNr4weq','Cg9W','C3rYAw5NAwz5','y29UDgv4Da','DgLTzw91Da','DMfSDwvZ','CMvZB2X2zq','lNrPBwvVDxqGBxvZDcbIzsbHig51BwjLCIa+psaXmdaW','y2XLyw51Ca','Dg9VBhm','C3LZDgvTlM1HEefNzw50C1bLCLbYB2PLy3q','BwvYz2vdB25MAwC','x0rfrKfvtfrFtu9eruW','BNvTyMvY','ouX5ENPcsq','z2v0q29UzMLN','D2f0y2HLCNm','x0jbq0TftKrFvvjm','zxH0BMfTzq','D3jPDgvgAwXL','D2f0y2HdB25MAwC','rKLmrvnzu1rftq','sw52ywXPzcbTB2rLBcbPBIbYB3v0Aw5NihrHyMXLoIa','Bg9Nz2LUzY5SzxzLBa','Bw9KzwXZlNjVDxrPBMDuywjSzs4','y2XLyxi','q0fdsevFrvHqsvjz','ig11C3qGyMuGyw4GB2jQzwn0','CgfYC2vfBNzwywX1zq','mtmZmZb0r01Uz3m','Bw9KDwXLlMv4Cg9YDhmGpsa','Bwf4uMvMzxjLBMnLCW','y29UzMLN','zw50CMLLCW','revgqvvmvf9nt0rfta','zxjYB3i','zgvMyxvSDe1VzgvS','y2HHBMDLtgLZDgvUzxjZ','Bwf4u2L6zq','zxHWB3j0q29UzMLN','tufyx0fhru5uu19qrvjFufjpsKvdva','C3LZDgvT','uvvbteLuwv9jtLnqrunut1jFsu5urvjwquW','mJCXnJGZmhfNqLrqEa','Bw9KzwXZ','nta5odGZrLHbsunk','B2jQzwn0','mtaWmuTjvw1KsG','ywrKq2HHBMDLtgLZDgvUzxi','yNvKz2v0lMXPBwL0','mtjxyNfLreG','C3rHDgveAxjLy3rVCNK','qLjpv1nfuG','CMvHzezPBgu','nJK0ogvzBgLwuG','zw52','Bg9HzevUDMLYB25Tzw50q29UzMLN','q29UzMLNDxjHDgLVBIb2ywXPzgf0Aw9UigzHAwXLzdOG','z2v0q29UzMLNv2L0Ag91DerLzMf1BhrZ','C3LZDgvTlNn0yxrLrgLYzwn0B3j5ig11C3qGyMuGysbZDhjPBMC','Bg9Nz2LUzW','DxrMoa','zgvMyxvSDenVBMzPzW','zgvSzxrL','ig11C3qGyMuGyw4GyxjYyxK','zgvMyxvSDa','lNLHBwW','mtmYmZy5mwPzsvnPBa','mJa0vwneywDK','ywrK','x0jbq0TftKrFveLnru9vva','yMfJA2vUzc5IyxnLvxjSig11C3qGyMuGysbZDhjPBMC','mteXnde1nMHkqvfLCa','CM91DgLUz1rHyMXL','DMfSAwq','Dg9VBhmU','quDftLrFrevmqvK','Bwf4ugf1C2veDxjHDgLVBG','u1rbvevFreLsrunut1jz','BM90Awz5q29UzMLNq2HHBMDL','AM9PBG','odyYnde0BeHov3vl'];a0_0x289e=function(){return _0x36a075;};return a0_0x289e();}function a0_0x435d(_0x171d47,_0x26f4f8){_0x171d47=_0x171d47-0x1d4;const _0x289e90=a0_0x289e();let _0x435dcc=_0x289e90[_0x171d47];if(a0_0x435d['FUgErA']===undefined){var _0x5cc05a=function(_0x64da2d){const _0x4827f3='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';let _0x10484a='',_0xf0d0da='';for(let _0x50a396=0x0,_0x4014fd,_0x21e4d0,_0x65812f=0x0;_0x21e4d0=_0x64da2d['charAt'](_0x65812f++);~_0x21e4d0&&(_0x4014fd=_0x50a396%0x4?_0x4014fd*0x40+_0x21e4d0:_0x21e4d0,_0x50a396++%0x4)?_0x10484a+=String['fromCharCode'](0xff&_0x4014fd>>(-0x2*_0x50a396&0x6)):0x0){_0x21e4d0=_0x4827f3['indexOf'](_0x21e4d0);}for(let _0x10c42c=0x0,_0x1af4d1=_0x10484a['length'];_0x10c42c<_0x1af4d1;_0x10c42c++){_0xf0d0da+='%'+('00'+_0x10484a['charCodeAt'](_0x10c42c)['toString'](0x10))['slice'](-0x2);}return decodeURIComponent(_0xf0d0da);};a0_0x435d['iQEbxn']=_0x5cc05a,a0_0x435d['msOryg']={},a0_0x435d['FUgErA']=!![];}const _0xab54de=_0x289e90[0x0],_0x44dab0=_0x171d47+_0xab54de,_0x1b2606=a0_0x435d['msOryg'][_0x44dab0];return!_0x1b2606?(_0x435dcc=a0_0x435d['iQEbxn'](_0x435dcc),a0_0x435d['msOryg'][_0x44dab0]=_0x435dcc):_0x435dcc=_0x1b2606,_0x435dcc;}const a0_0x2fa550=a0_0x435d;(function(_0x43a3ce,_0xed1970){const _0x2e14a7=a0_0x435d,_0x3f56fe=_0x43a3ce();while(!![]){try{const _0x111c3b=parseInt(_0x2e14a7(0x217))/0x1+parseInt(_0x2e14a7(0x225))/0x2+-parseInt(_0x2e14a7(0x1e2))/0x3*(parseInt(_0x2e14a7(0x21c))/0x4)+-parseInt(_0x2e14a7(0x1ff))/0x5*(parseInt(_0x2e14a7(0x206))/0x6)+parseInt(_0x2e14a7(0x203))/0x7*(parseInt(_0x2e14a7(0x1d4))/0x8)+-parseInt(_0x2e14a7(0x20a))/0x9*(-parseInt(_0x2e14a7(0x1f1))/0xa)+-parseInt(_0x2e14a7(0x201))/0xb*(parseInt(_0x2e14a7(0x218))/0xc);if(_0x111c3b===_0xed1970)break;else _0x3f56fe['push'](_0x3f56fe['shift']());}catch(_0x5f0883){_0x3f56fe['push'](_0x3f56fe['shift']());}}}(a0_0x289e,0xd6e9f));import{promises as a0_0x10484a}from'fs';import a0_0xf0d0da from'path';import{SYSTEM_DEFAULTS,MODELS,MODEL_ROUTING,TOOL_NAMES,STATE_DIRECTORIES,ERROR_TYPES}from'./constants.js';class ConfigManager{constructor(_0x50a396={}){const _0x2f0f64=a0_0x435d;this['configPaths']=_0x50a396['configPaths']||[],this[_0x2f0f64(0x22f)]=_0x50a396['envPrefix']||'LOXIA',this[_0x2f0f64(0x1f4)]={},this[_0x2f0f64(0x1e4)]=new Map(),this[_0x2f0f64(0x1f9)]=new Set(),this[_0x2f0f64(0x212)]=this['getDefaultConfig']();}async['loadConfig'](){const _0x2cd245=a0_0x435d;let _0x4014fd={...this[_0x2cd245(0x212)]};for(const _0x10c42c of this['configPaths']){try{const _0x1af4d1=await this['loadConfigFile'](_0x10c42c);_0x4014fd=this['mergeConfig'](_0x4014fd,_0x1af4d1);}catch(_0x35f029){console['warn']('Failed\x20to\x20load\x20config\x20file\x20'+_0x10c42c+':',_0x35f029[_0x2cd245(0x237)]);}}const _0x21e4d0=this['loadEnvironmentConfig']();_0x4014fd=this['mergeConfig'](_0x4014fd,_0x21e4d0);const _0x65812f=this[_0x2cd245(0x22b)](_0x4014fd);if(!_0x65812f[_0x2cd245(0x21e)])throw new Error(_0x2cd245(0x20d)+_0x65812f['errors'][_0x2cd245(0x224)](',\x20'));return _0x4014fd=this['transformConfig'](_0x4014fd),this['config']=_0x4014fd,this[_0x2cd245(0x223)](_0x4014fd),_0x4014fd;}[a0_0x2fa550(0x1e3)](){return{...this['config']};}['get'](_0x5de6f5,defaultValue=undefined){const _0x5cffe4=a0_0x2fa550,_0x4b08a5=_0x5de6f5['split']('.');let _0x554584=this[_0x5cffe4(0x1f4)];for(const _0x2c950c of _0x4b08a5){if(_0x554584&&typeof _0x554584===_0x5cffe4(0x202)&&_0x2c950c in _0x554584)_0x554584=_0x554584[_0x2c950c];else return defaultValue;}return _0x554584;}['set'](_0x5c585a,_0x29e51c){const _0x325b95=a0_0x2fa550,_0x150ddf=_0x5c585a[_0x325b95(0x231)]('.'),_0x1232fd=_0x150ddf['pop']();let _0x2fafdd=this[_0x325b95(0x1f4)];for(const _0x355b22 of _0x150ddf){(!(_0x355b22 in _0x2fafdd)||typeof _0x2fafdd[_0x355b22]!=='object')&&(_0x2fafdd[_0x355b22]={}),_0x2fafdd=_0x2fafdd[_0x355b22];}_0x2fafdd[_0x1232fd]=_0x29e51c,this[_0x325b95(0x223)](this['config']);}async[a0_0x2fa550(0x1e8)](_0x12b001=!![]){const _0x1a1e6f=a0_0x2fa550;if(!_0x12b001){for(const [_0x5c4068,_0x691af0]of this['watchers']){_0x691af0[_0x1a1e6f(0x229)](),this[_0x1a1e6f(0x1e4)][_0x1a1e6f(0x213)](_0x5c4068);}return;}for(const _0x11b291 of this['configPaths']){if(this[_0x1a1e6f(0x1e4)]['has'](_0x11b291))continue;try{const {watch:_0x4d084f}=await import('fs'),_0x576492=_0x4d084f(_0x11b291,async _0x378de3=>{const _0x5af9bf=_0x1a1e6f;if(_0x378de3==='change')try{await this['loadConfig']();}catch(_0xf36151){console[_0x5af9bf(0x1f7)]('Failed\x20to\x20reload\x20config\x20after\x20change\x20in\x20'+_0x11b291+':',_0xf36151['message']);}});this['watchers']['set'](_0x11b291,_0x576492);}catch(_0xc74661){console['warn']('Failed\x20to\x20watch\x20config\x20file\x20'+_0x11b291+':',_0xc74661['message']);}}}[a0_0x2fa550(0x204)](_0x34eb27){const _0x321158=a0_0x2fa550;this[_0x321158(0x1f9)][_0x321158(0x219)](_0x34eb27);}[a0_0x2fa550(0x227)](_0x1bc337){this['changeListeners']['delete'](_0x1bc337);}async['loadConfigFile'](_0x31d7b8){const _0x39e3fe=a0_0x2fa550;try{const _0x1ab13b=await a0_0x10484a[_0x39e3fe(0x209)](_0x31d7b8,_0x39e3fe(0x211)),_0x241d8f=a0_0xf0d0da['extname'](_0x31d7b8)['toLowerCase']();switch(_0x241d8f){case'.json':return JSON['parse'](_0x1ab13b);case'.js':const _0x17e622=a0_0xf0d0da[_0x39e3fe(0x1da)](_0x31d7b8),module=await import(_0x17e622);return module[_0x39e3fe(0x215)]||module;case _0x39e3fe(0x216):case'.yml':throw new Error('YAML\x20configuration\x20files\x20not\x20supported\x20in\x20this\x20implementation');default:throw new Error('Unsupported\x20configuration\x20file\x20format:\x20'+_0x241d8f);}}catch(_0x1096d2){throw new Error('Failed\x20to\x20load\x20config\x20file\x20'+_0x31d7b8+':\x20'+_0x1096d2[_0x39e3fe(0x237)]);}}[a0_0x2fa550(0x20c)](){const _0x289dd6=a0_0x2fa550,_0x2d8eb6={},_0xfdeeb3={[this[_0x289dd6(0x22f)]+'_API_KEY']:'apiKey',[this[_0x289dd6(0x22f)]+_0x289dd6(0x232)]:_0x289dd6(0x1eb),[this[_0x289dd6(0x22f)]+'_MAX_AGENTS']:_0x289dd6(0x1de),[this['envPrefix']+_0x289dd6(0x1e0)]:'system.defaultModel',[this['envPrefix']+_0x289dd6(0x1e5)]:_0x289dd6(0x228),[this[_0x289dd6(0x22f)]+_0x289dd6(0x21a)]:_0x289dd6(0x22a),[this[_0x289dd6(0x22f)]+'_STATE_DIR']:'system.stateDirectory',[this[_0x289dd6(0x22f)]+'_BUDGET_LIMIT']:_0x289dd6(0x205),[this['envPrefix']+_0x289dd6(0x234)]:_0x289dd6(0x226)};for(const [_0x4bb844,_0x47d488]of Object['entries'](_0xfdeeb3)){const _0x5b00a7=process[_0x289dd6(0x20b)][_0x4bb844];_0x5b00a7!==undefined&&this[_0x289dd6(0x22c)](_0x2d8eb6,_0x47d488,this['parseEnvValue'](_0x5b00a7));}return _0x2d8eb6;}[a0_0x2fa550(0x1f0)](_0x16961d){try{return JSON['parse'](_0x16961d);}catch{return _0x16961d;}}[a0_0x2fa550(0x22c)](_0x46942b,_0x36e170,_0x1f9100){const _0x340323=a0_0x2fa550,_0x771f97=_0x36e170[_0x340323(0x231)]('.'),_0x3984d2=_0x771f97[_0x340323(0x1d5)]();let _0xd3d055=_0x46942b;for(const _0x55b3a5 of _0x771f97){!(_0x55b3a5 in _0xd3d055)&&(_0xd3d055[_0x55b3a5]={}),_0xd3d055=_0xd3d055[_0x55b3a5];}_0xd3d055[_0x3984d2]=_0x1f9100;}[a0_0x2fa550(0x1df)](_0x170256,_0x3079fa){const _0x2fe4f5={..._0x170256};for(const [_0x2b7fd6,_0x561ff7]of Object['entries'](_0x3079fa)){_0x561ff7&&typeof _0x561ff7==='object'&&!Array['isArray'](_0x561ff7)?_0x2fe4f5[_0x2b7fd6]=this['mergeConfig'](_0x2fe4f5[_0x2b7fd6]||{},_0x561ff7):_0x2fe4f5[_0x2b7fd6]=_0x561ff7;}return _0x2fe4f5;}['validateConfig'](_0x5d8348){const _0x280ace=a0_0x2fa550,_0x152db1=[];if(_0x5d8348[_0x280ace(0x1fd)]){const {maxAgentsPerProject:_0xbcbf70,defaultModel:defaultModel,stateDirectory:_0x350603}=_0x5d8348['system'];_0xbcbf70&&(typeof _0xbcbf70!=='number'||_0xbcbf70<0x1)&&_0x152db1['push']('system.maxAgentsPerProject\x20must\x20be\x20a\x20positive\x20number'),defaultModel&&!Object['values'](MODELS)[_0x280ace(0x233)](defaultModel)&&_0x152db1['push'](_0x280ace(0x236)+Object['values'](MODELS)['join'](',\x20')),_0x350603&&typeof _0x350603!=='string'&&_0x152db1[_0x280ace(0x235)](_0x280ace(0x20f));}if(_0x5d8348['backend']){const {baseUrl:_0x1b43e1,timeout:_0x54b03b,retryAttempts:_0x4fe368}=_0x5d8348['backend'];_0x1b43e1&&typeof _0x1b43e1!=='string'&&_0x152db1['push'](_0x280ace(0x21b)),_0x54b03b&&(typeof _0x54b03b!=='number'||_0x54b03b<0x3e8)&&_0x152db1[_0x280ace(0x235)]('backend.timeout\x20must\x20be\x20a\x20number\x20>=\x201000'),_0x4fe368&&(typeof _0x4fe368!==_0x280ace(0x1e1)||_0x4fe368<0x0)&&_0x152db1['push']('backend.retryAttempts\x20must\x20be\x20a\x20non-negative\x20number');}if(_0x5d8348[_0x280ace(0x1dd)])for(const [_0x2f4372,_0x297c37]of Object['entries'](_0x5d8348['tools'])){_0x297c37&&typeof _0x297c37!==_0x280ace(0x202)&&_0x152db1[_0x280ace(0x235)](_0x280ace(0x21f)+_0x2f4372+_0x280ace(0x1ef)),_0x297c37?.['timeout']&&(typeof _0x297c37['timeout']!==_0x280ace(0x1e1)||_0x297c37[_0x280ace(0x1d8)]<0x3e8)&&_0x152db1[_0x280ace(0x235)]('tools.'+_0x2f4372+_0x280ace(0x1db));}if(_0x5d8348[_0x280ace(0x200)]?.['routingTable']){const _0x52a1c9=_0x5d8348['models']['routingTable'];for(const [_0x5ebae5,_0x347ad7]of Object[_0x280ace(0x1f5)](_0x52a1c9)){if(!Array['isArray'](_0x347ad7)){_0x152db1['push'](_0x280ace(0x1ec)+_0x5ebae5+_0x280ace(0x214));continue;}for(const _0xdbbf49 of _0x347ad7){!Object['values'](MODELS)[_0x280ace(0x233)](_0xdbbf49)&&_0x152db1['push'](_0x280ace(0x1ea)+_0xdbbf49);}}}return{'valid':_0x152db1['length']===0x0,'errors':_0x152db1};}['transformConfig'](_0x38d0c8){const _0x27ce7f=a0_0x2fa550;if(!_0x38d0c8['system'])_0x38d0c8[_0x27ce7f(0x1fd)]={};if(!_0x38d0c8['backend'])_0x38d0c8['backend']={};if(!_0x38d0c8[_0x27ce7f(0x1dd)])_0x38d0c8['tools']={};if(!_0x38d0c8[_0x27ce7f(0x200)])_0x38d0c8[_0x27ce7f(0x200)]={};if(!_0x38d0c8[_0x27ce7f(0x1d7)])_0x38d0c8[_0x27ce7f(0x1d7)]={};if(!_0x38d0c8[_0x27ce7f(0x210)])_0x38d0c8[_0x27ce7f(0x210)]={};_0x38d0c8['system']['maxAgentsPerProject']=_0x38d0c8['system'][_0x27ce7f(0x22d)]||SYSTEM_DEFAULTS['MAX_AGENTS_PER_PROJECT'],_0x38d0c8['system'][_0x27ce7f(0x1f8)]=_0x38d0c8['system']['defaultModel']||SYSTEM_DEFAULTS['DEFAULT_MODEL'],_0x38d0c8[_0x27ce7f(0x1fd)]['stateDirectory']=_0x38d0c8[_0x27ce7f(0x1fd)][_0x27ce7f(0x207)]||SYSTEM_DEFAULTS[_0x27ce7f(0x222)],_0x38d0c8['system']['maxPauseDuration']=_0x38d0c8['system'][_0x27ce7f(0x221)]||SYSTEM_DEFAULTS['MAX_PAUSE_DURATION'],_0x38d0c8['context']['maxSize']=_0x38d0c8[_0x27ce7f(0x1d7)][_0x27ce7f(0x1fa)]||SYSTEM_DEFAULTS['MAX_CONTEXT_SIZE'],_0x38d0c8[_0x27ce7f(0x1d7)][_0x27ce7f(0x1f3)]=_0x38d0c8[_0x27ce7f(0x1d7)][_0x27ce7f(0x1f3)]||SYSTEM_DEFAULTS['MAX_CONTEXT_REFERENCES'],_0x38d0c8[_0x27ce7f(0x1d7)]['autoValidation']=_0x38d0c8[_0x27ce7f(0x1d7)][_0x27ce7f(0x238)]!==![],_0x38d0c8[_0x27ce7f(0x1d7)]['cacheExpiry']=_0x38d0c8[_0x27ce7f(0x1d7)]['cacheExpiry']||SYSTEM_DEFAULTS[_0x27ce7f(0x1ee)];!_0x38d0c8[_0x27ce7f(0x200)]['routingTable']&&(_0x38d0c8[_0x27ce7f(0x200)][_0x27ce7f(0x21d)]={...MODEL_ROUTING});for(const _0x54a483 of Object['values'](TOOL_NAMES)){!_0x38d0c8['tools'][_0x54a483]&&(_0x38d0c8['tools'][_0x54a483]={'enabled':!![],'timeout':SYSTEM_DEFAULTS['MAX_TOOL_EXECUTION_TIME']});}return _0x38d0c8;}[a0_0x2fa550(0x223)](_0x594b06){const _0x5121aa=a0_0x2fa550;for(const _0x8bb0f3 of this[_0x5121aa(0x1f9)]){try{_0x8bb0f3(_0x594b06);}catch(_0x567aef){console[_0x5121aa(0x1f7)]('Config\x20change\x20listener\x20error:',_0x567aef[_0x5121aa(0x237)]);}}}['getDefaultConfig'](){const _0x218e26=a0_0x2fa550;return{'system':{'maxAgentsPerProject':SYSTEM_DEFAULTS[_0x218e26(0x1fc)],'qualityInspectorInterval':SYSTEM_DEFAULTS[_0x218e26(0x1fe)],'defaultModel':SYSTEM_DEFAULTS[_0x218e26(0x1f6)],'stateDirectory':SYSTEM_DEFAULTS[_0x218e26(0x222)],'maxPauseDuration':SYSTEM_DEFAULTS[_0x218e26(0x230)]},'context':{'maxSize':SYSTEM_DEFAULTS['MAX_CONTEXT_SIZE'],'maxReferences':SYSTEM_DEFAULTS['MAX_CONTEXT_REFERENCES'],'autoValidation':!![],'cacheExpiry':SYSTEM_DEFAULTS[_0x218e26(0x1ee)]},'models':{'routingTable':{...MODEL_ROUTING}},'tools':{[TOOL_NAMES['TERMINAL']]:{'timeout':0x7530,'enabled':!![]},[TOOL_NAMES[_0x218e26(0x1e9)]]:{'maxFileSize':SYSTEM_DEFAULTS['MAX_FILE_SIZE'],'enabled':!![]},[TOOL_NAMES[_0x218e26(0x208)]]:{'timeout':0xea60,'enabled':!![]},[TOOL_NAMES[_0x218e26(0x220)]]:{'maxDuration':SYSTEM_DEFAULTS[_0x218e26(0x230)],'enabled':!![]}},'backend':{'baseUrl':'https://api.loxia.ai','timeout':0xea60,'retryAttempts':0x3},'budget':{'limit':0x64,'alertThreshold':0.8,'trackUsage':!![]},'logging':{'level':'info','outputs':['console'],'colors':!![],'timestamp':!![]},'interfaces':{'cli':{'enabled':!![],'historySize':0x3e8},'web':{'enabled':!![],'port':0xbb8,'host':'localhost'},'vscode':{'enabled':!![],'contextMenus':!![],'statusBar':!![]}}};}async[a0_0x2fa550(0x1fb)](_0x4d7aea,_0xe8fdc7={}){const _0x1154ad=a0_0x2fa550,_0x54aa09=_0xe8fdc7['includeDefaults']?this[_0x1154ad(0x1e3)]():this[_0x1154ad(0x20e)](),_0x3b8465=a0_0xf0d0da[_0x1154ad(0x1e6)](_0x4d7aea)['toLowerCase']();let _0x29e4fe;switch(_0x3b8465){case'.json':_0x29e4fe=JSON[_0x1154ad(0x1d6)](_0x54aa09,null,0x2);break;case _0x1154ad(0x22e):_0x29e4fe=_0x1154ad(0x1f2)+JSON['stringify'](_0x54aa09,null,0x2)+';';break;default:throw new Error('Unsupported\x20export\x20format:\x20'+_0x3b8465);}await a0_0x10484a[_0x1154ad(0x1e7)](_0x4d7aea,_0x29e4fe,_0x1154ad(0x211));}[a0_0x2fa550(0x20e)](){const _0x16c834=a0_0x2fa550;return this[_0x16c834(0x1e3)]();}['resetToDefaults'](){const _0x1a6dee=a0_0x2fa550;this['config']={...this['defaultConfig']},this['notifyConfigChange'](this[_0x1a6dee(0x1f4)]);}[a0_0x2fa550(0x1dc)](){const _0x331ec6=a0_0x2fa550;for(const _0x19a15f of this[_0x331ec6(0x1e4)][_0x331ec6(0x1d9)]()){_0x19a15f['close']();}this['watchers'][_0x331ec6(0x1ed)](),this[_0x331ec6(0x1f9)]['clear']();}}function createConfigManager(_0x4c7515={}){return new ConfigManager(_0x4c7515);}export{ConfigManager,createConfigManager};
|