@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,1215 +1 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @file tools/dependencyResolverTool.js
|
|
3
|
-
* @description Modern tool for resolving Node.js dependency conflicts by checking and updating to latest compatible versions
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { promises as fs } from 'fs';
|
|
7
|
-
import path from 'path';
|
|
8
|
-
import { exec as execCb } from 'child_process';
|
|
9
|
-
import { promisify } from 'util';
|
|
10
|
-
import { BaseTool } from './baseTool.js';
|
|
11
|
-
import TagParser from '../utilities/tagParser.js';
|
|
12
|
-
|
|
13
|
-
const exec = promisify(execCb);
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Configuration constants for the dependency resolver
|
|
17
|
-
*/
|
|
18
|
-
const RESOLVER_CONFIG = {
|
|
19
|
-
DEFAULT_MODE: 'check',
|
|
20
|
-
VALID_MODES: ['check', 'fix', 'auto'],
|
|
21
|
-
NPM_COMMAND_TIMEOUT: 300000, // 5 minutes for npm commands
|
|
22
|
-
REGISTRY_TIMEOUT: 10000, // 10 seconds for registry requests
|
|
23
|
-
MAX_CONCURRENT_CHECKS: 5, // Max parallel registry checks
|
|
24
|
-
BACKUP_EXTENSION: '.backup.json', // Backup file extension
|
|
25
|
-
CREATE_BACKUPS: true, // Always create backups
|
|
26
|
-
RETRY_ATTEMPTS: 3, // Registry request retry attempts
|
|
27
|
-
RETRY_DELAY: 1000, // Delay between retries (ms)
|
|
28
|
-
MAX_DEPENDENCIES: 500, // Safety limit
|
|
29
|
-
NPM_REGISTRY_URL: 'https://registry.npmjs.org'
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* DependencyResolverTool - Modern implementation
|
|
34
|
-
* Resolves Node.js package dependency conflicts with improved security and reliability
|
|
35
|
-
*/
|
|
36
|
-
export class DependencyResolverTool extends BaseTool {
|
|
37
|
-
/**
|
|
38
|
-
* Get tool description for agent system prompt
|
|
39
|
-
* @returns {string} Formatted tool description
|
|
40
|
-
*/
|
|
41
|
-
getDescription() {
|
|
42
|
-
return `Tool: Dependency Resolver - Resolve Node.js package dependency conflicts
|
|
43
|
-
|
|
44
|
-
**Purpose:** Checks npm dependencies for updates and optionally updates package.json to latest compatible versions automatically.
|
|
45
|
-
|
|
46
|
-
**Invocation Syntax:**
|
|
47
|
-
|
|
48
|
-
XML Format:
|
|
49
|
-
\`\`\`xml
|
|
50
|
-
<dependency-resolve>
|
|
51
|
-
<path>./my-project</path>
|
|
52
|
-
<mode>check</mode>
|
|
53
|
-
<include-dev>true</include-dev>
|
|
54
|
-
</dependency-resolve>
|
|
55
|
-
\`\`\`
|
|
56
|
-
|
|
57
|
-
JSON Format:
|
|
58
|
-
\`\`\`json
|
|
59
|
-
{
|
|
60
|
-
"toolId": "dependency-resolver",
|
|
61
|
-
"parameters": {
|
|
62
|
-
"path": "./my-project",
|
|
63
|
-
"mode": "check",
|
|
64
|
-
"includeDev": true
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
\`\`\`
|
|
68
|
-
|
|
69
|
-
**Parameters:**
|
|
70
|
-
- **path** (string, optional): Path to project directory with package.json. Default: "."
|
|
71
|
-
- **mode** (string, optional): Operation mode. Options:
|
|
72
|
-
- "check" - Only check for updates (default)
|
|
73
|
-
- "fix" - Update package.json and run npm install
|
|
74
|
-
- "auto" - Automatically fix all conflicts
|
|
75
|
-
- **includeDev** (boolean, optional): Include devDependencies. Default: true
|
|
76
|
-
|
|
77
|
-
**What It Does:**
|
|
78
|
-
- Checks npm registry for latest compatible versions
|
|
79
|
-
- Respects semver ranges (^, ~, >=, etc.)
|
|
80
|
-
- Creates automatic backups before modifications
|
|
81
|
-
- Runs npm install after updates (in fix/auto mode)
|
|
82
|
-
- Provides detailed update report
|
|
83
|
-
|
|
84
|
-
**Examples:**
|
|
85
|
-
|
|
86
|
-
1. Check for updates:
|
|
87
|
-
\`\`\`xml
|
|
88
|
-
<dependency-resolver>
|
|
89
|
-
<mode>check</mode>
|
|
90
|
-
</dependency-resolver>
|
|
91
|
-
\`\`\`
|
|
92
|
-
|
|
93
|
-
2. Fix outdated dependencies:
|
|
94
|
-
\`\`\`xml
|
|
95
|
-
<dependency-resolver>
|
|
96
|
-
<path>./my-project</path>
|
|
97
|
-
<mode>fix</mode>
|
|
98
|
-
</dependency-resolver>
|
|
99
|
-
\`\`\`
|
|
100
|
-
|
|
101
|
-
3. Auto-fix with devDependencies:
|
|
102
|
-
\`\`\`json
|
|
103
|
-
{
|
|
104
|
-
"toolId": "dependency-resolver",
|
|
105
|
-
"parameters": { "mode": "auto", "includeDev": true }
|
|
106
|
-
}
|
|
107
|
-
\`\`\`
|
|
108
|
-
|
|
109
|
-
**Notes:**
|
|
110
|
-
- Always creates backup (.backup.json) before modifications
|
|
111
|
-
- Network requests have timeout and retry logic
|
|
112
|
-
- npm install runs with timeout protection (5 minutes max)
|
|
113
|
-
- Supports complex semver ranges (||, &&, etc.)`;
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
/**
|
|
117
|
-
* Parse tool parameters from raw content (XML or JSON)
|
|
118
|
-
* @param {string|Object} content - Raw tool content or parsed object
|
|
119
|
-
* @returns {Object} Parsed parameters
|
|
120
|
-
*/
|
|
121
|
-
parseParameters(content) {
|
|
122
|
-
// If already an object, validate and return
|
|
123
|
-
if (typeof content === 'object' && content !== null) {
|
|
124
|
-
return {
|
|
125
|
-
path: content.path || '.',
|
|
126
|
-
mode: content.mode || RESOLVER_CONFIG.DEFAULT_MODE,
|
|
127
|
-
includeDev: content.includeDev !== undefined ? content.includeDev : true
|
|
128
|
-
};
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
// Parse XML content
|
|
132
|
-
if (typeof content === 'string') {
|
|
133
|
-
// Try modern XML format first: <dependency-resolve>...</dependency-resolve>
|
|
134
|
-
const modernPattern = /<dependency-resolve([^>]*)>([\s\S]*?)<\/dependency-resolve>/i;
|
|
135
|
-
const modernMatch = modernPattern.exec(content);
|
|
136
|
-
|
|
137
|
-
if (modernMatch) {
|
|
138
|
-
const attributesStr = modernMatch[1];
|
|
139
|
-
const innerContent = modernMatch[2];
|
|
140
|
-
|
|
141
|
-
// Parse attributes from opening tag
|
|
142
|
-
const pathAttr = /path=["']([^"']*)["']/i.exec(attributesStr);
|
|
143
|
-
const modeAttr = /mode=["']([^"']*)["']/i.exec(attributesStr);
|
|
144
|
-
const includeDevAttr = /include-dev=["']([^"']*)["']/i.exec(attributesStr);
|
|
145
|
-
|
|
146
|
-
// Extract from inner content
|
|
147
|
-
const pathPattern = /<path>(.*?)<\/path>/i;
|
|
148
|
-
const pathMatch = pathPattern.exec(innerContent);
|
|
149
|
-
|
|
150
|
-
const modePattern = /<mode>(.*?)<\/mode>/i;
|
|
151
|
-
const modeMatch = modePattern.exec(innerContent);
|
|
152
|
-
|
|
153
|
-
const includeDevPattern = /<include-dev>(.*?)<\/include-dev>/i;
|
|
154
|
-
const includeDevMatch = includeDevPattern.exec(innerContent);
|
|
155
|
-
|
|
156
|
-
// Content takes precedence over attributes
|
|
157
|
-
const extractedPath = (pathMatch ? pathMatch[1].trim() : null) || (pathAttr ? pathAttr[1] : '.');
|
|
158
|
-
const extractedMode = (modeMatch ? modeMatch[1].trim() : null) || (modeAttr ? modeAttr[1] : RESOLVER_CONFIG.DEFAULT_MODE);
|
|
159
|
-
const extractedIncludeDev = (includeDevMatch ? includeDevMatch[1].trim() : null) || (includeDevAttr ? includeDevAttr[1] : 'true');
|
|
160
|
-
|
|
161
|
-
return {
|
|
162
|
-
path: extractedPath,
|
|
163
|
-
mode: extractedMode,
|
|
164
|
-
includeDev: this._parseBoolean(extractedIncludeDev, true)
|
|
165
|
-
};
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
// Try legacy format: [resolve path="..." mode="..."]
|
|
169
|
-
const legacyPattern = /\[resolve\s+([^\]]*)\]/i;
|
|
170
|
-
const legacyMatch = legacyPattern.exec(content);
|
|
171
|
-
|
|
172
|
-
if (legacyMatch) {
|
|
173
|
-
const attrString = legacyMatch[1];
|
|
174
|
-
|
|
175
|
-
// Parse attributes manually
|
|
176
|
-
const pathAttr = /path=["']([^"']*)["']/i.exec(attrString);
|
|
177
|
-
const modeAttr = /mode=["']([^"']*)["']/i.exec(attrString);
|
|
178
|
-
const includeDevAttr = /include-dev=["']([^"']*)["']/i.exec(attrString);
|
|
179
|
-
|
|
180
|
-
return {
|
|
181
|
-
path: pathAttr ? pathAttr[1] : '.',
|
|
182
|
-
mode: modeAttr ? modeAttr[1] : RESOLVER_CONFIG.DEFAULT_MODE,
|
|
183
|
-
includeDev: this._parseBoolean(includeDevAttr ? includeDevAttr[1] : 'true', true)
|
|
184
|
-
};
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
throw new Error('Invalid dependency-resolve format. Use <dependency-resolve> tags or JSON format.');
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
throw new Error('Invalid parameter format. Expected string (XML) or object (JSON).');
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
/**
|
|
194
|
-
* Parse boolean from string or boolean
|
|
195
|
-
* @param {any} value - Value to parse
|
|
196
|
-
* @param {boolean} defaultValue - Default if undefined
|
|
197
|
-
* @returns {boolean}
|
|
198
|
-
* @private
|
|
199
|
-
*/
|
|
200
|
-
_parseBoolean(value, defaultValue = false) {
|
|
201
|
-
if (value === undefined || value === null) return defaultValue;
|
|
202
|
-
if (typeof value === 'boolean') return value;
|
|
203
|
-
if (typeof value === 'string') {
|
|
204
|
-
return value.toLowerCase() === 'true' || value === '1';
|
|
205
|
-
}
|
|
206
|
-
return defaultValue;
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
/**
|
|
210
|
-
* Validate parameters
|
|
211
|
-
* @param {Object} params - Parameters to validate
|
|
212
|
-
* @throws {Error} If validation fails
|
|
213
|
-
* @private
|
|
214
|
-
*/
|
|
215
|
-
_validateParameters(params) {
|
|
216
|
-
if (!params || typeof params !== 'object') {
|
|
217
|
-
throw new Error('Parameters must be an object');
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
if (params.path && typeof params.path !== 'string') {
|
|
221
|
-
throw new Error('path must be a string');
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
if (params.mode && !RESOLVER_CONFIG.VALID_MODES.includes(params.mode)) {
|
|
225
|
-
throw new Error(`Invalid mode: ${params.mode}. Must be one of: ${RESOLVER_CONFIG.VALID_MODES.join(', ')}`);
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
if (params.includeDev !== undefined && typeof params.includeDev !== 'boolean') {
|
|
229
|
-
throw new Error('includeDev must be a boolean');
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
/**
|
|
234
|
-
* Validate and resolve file path
|
|
235
|
-
* @param {string} targetPath - Target path from parameters
|
|
236
|
-
* @param {Object} context - Execution context
|
|
237
|
-
* @returns {string} Resolved absolute path
|
|
238
|
-
* @throws {Error} If path is invalid or inaccessible
|
|
239
|
-
* @private
|
|
240
|
-
*/
|
|
241
|
-
_resolveAndValidatePath(targetPath, context) {
|
|
242
|
-
const { projectDir, directoryAccess } = context;
|
|
243
|
-
|
|
244
|
-
// Determine working directory
|
|
245
|
-
let workingDirectory = projectDir || process.cwd();
|
|
246
|
-
|
|
247
|
-
if (directoryAccess && directoryAccess.workingDirectory) {
|
|
248
|
-
workingDirectory = directoryAccess.workingDirectory;
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
// Resolve the target path
|
|
252
|
-
const resolvedPath = path.isAbsolute(targetPath)
|
|
253
|
-
? path.normalize(targetPath)
|
|
254
|
-
: path.normalize(path.join(workingDirectory, targetPath));
|
|
255
|
-
|
|
256
|
-
// Security: Check for path traversal
|
|
257
|
-
const realWorkingDir = path.normalize(workingDirectory);
|
|
258
|
-
if (!resolvedPath.startsWith(realWorkingDir)) {
|
|
259
|
-
throw new Error(`Path traversal detected: ${targetPath} resolves outside working directory`);
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
return resolvedPath;
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
/**
|
|
266
|
-
* Create backup of package.json
|
|
267
|
-
* @param {string} pkgPath - Path to package.json
|
|
268
|
-
* @returns {Promise<string|null>} Backup file path or null if failed
|
|
269
|
-
* @private
|
|
270
|
-
*/
|
|
271
|
-
async _createBackup(pkgPath) {
|
|
272
|
-
if (!RESOLVER_CONFIG.CREATE_BACKUPS) {
|
|
273
|
-
return null;
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
try {
|
|
277
|
-
const backupPath = pkgPath + RESOLVER_CONFIG.BACKUP_EXTENSION;
|
|
278
|
-
await fs.copyFile(pkgPath, backupPath);
|
|
279
|
-
this.logger?.info('Created backup', { backupPath });
|
|
280
|
-
return backupPath;
|
|
281
|
-
} catch (error) {
|
|
282
|
-
this.logger?.warn('Failed to create backup', { error: error.message });
|
|
283
|
-
return null;
|
|
284
|
-
}
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
/**
|
|
288
|
-
* Fetch package info from npm registry with retries
|
|
289
|
-
* @param {string} packageName - Package name
|
|
290
|
-
* @returns {Promise<Object|null>} Package data or null if failed
|
|
291
|
-
* @private
|
|
292
|
-
*/
|
|
293
|
-
async _fetchPackageInfo(packageName) {
|
|
294
|
-
const url = `${RESOLVER_CONFIG.NPM_REGISTRY_URL}/${encodeURIComponent(packageName)}`;
|
|
295
|
-
|
|
296
|
-
for (let attempt = 1; attempt <= RESOLVER_CONFIG.RETRY_ATTEMPTS; attempt++) {
|
|
297
|
-
try {
|
|
298
|
-
const controller = new AbortController();
|
|
299
|
-
const timeout = setTimeout(() => controller.abort(), RESOLVER_CONFIG.REGISTRY_TIMEOUT);
|
|
300
|
-
|
|
301
|
-
const response = await fetch(url, { signal: controller.signal });
|
|
302
|
-
clearTimeout(timeout);
|
|
303
|
-
|
|
304
|
-
if (!response.ok) {
|
|
305
|
-
if (response.status === 404) {
|
|
306
|
-
this.logger?.warn(`Package not found: ${packageName}`);
|
|
307
|
-
return null;
|
|
308
|
-
}
|
|
309
|
-
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
const data = await response.json();
|
|
313
|
-
|
|
314
|
-
// Validate response structure
|
|
315
|
-
if (!data || typeof data !== 'object' || !data['dist-tags']) {
|
|
316
|
-
throw new Error('Invalid registry response format');
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
return data;
|
|
320
|
-
|
|
321
|
-
} catch (error) {
|
|
322
|
-
if (attempt < RESOLVER_CONFIG.RETRY_ATTEMPTS) {
|
|
323
|
-
this.logger?.debug(`Retry ${attempt}/${RESOLVER_CONFIG.RETRY_ATTEMPTS} for ${packageName}`);
|
|
324
|
-
await new Promise(resolve => setTimeout(resolve, RESOLVER_CONFIG.RETRY_DELAY * attempt));
|
|
325
|
-
} else {
|
|
326
|
-
this.logger?.error(`Failed to fetch ${packageName}:`, error.message);
|
|
327
|
-
return null;
|
|
328
|
-
}
|
|
329
|
-
}
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
return null;
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
/**
|
|
336
|
-
* Get latest compatible version for a package
|
|
337
|
-
* Enhanced self-contained semver logic supporting:
|
|
338
|
-
* - Caret ranges (^) with 0.x.y and 0.0.x special cases
|
|
339
|
-
* - Tilde ranges (~)
|
|
340
|
-
* - Comparison operators (>, >=, <, <=)
|
|
341
|
-
* - X-ranges (4.x, 4.*, etc.)
|
|
342
|
-
* - Pre-release versions
|
|
343
|
-
* - Complex range expressions (AND/OR)
|
|
344
|
-
* - Exact versions
|
|
345
|
-
*
|
|
346
|
-
* @param {string} packageName - Package name
|
|
347
|
-
* @param {string} currentRange - Current version range
|
|
348
|
-
* @returns {Promise<string|null>} Latest version or null if no update needed
|
|
349
|
-
* @private
|
|
350
|
-
*/
|
|
351
|
-
async _getLatestCompatibleVersion(packageName, currentRange) {
|
|
352
|
-
const data = await this._fetchPackageInfo(packageName);
|
|
353
|
-
|
|
354
|
-
if (!data) {
|
|
355
|
-
return null;
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
const latest = data['dist-tags']?.latest;
|
|
359
|
-
|
|
360
|
-
if (!latest) {
|
|
361
|
-
return null;
|
|
362
|
-
}
|
|
363
|
-
|
|
364
|
-
// Parse latest version
|
|
365
|
-
const latestParsed = this._parseVersion(latest);
|
|
366
|
-
|
|
367
|
-
if (!latestParsed) {
|
|
368
|
-
return null; // Can't parse latest
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
// Check if it's a complex range (AND/OR)
|
|
372
|
-
if (this._isComplexRange(currentRange)) {
|
|
373
|
-
const complexRange = this._parseComplexRange(currentRange);
|
|
374
|
-
const isUpdateAvailable = this._satisfiesComplexRange(complexRange, latestParsed);
|
|
375
|
-
|
|
376
|
-
if (isUpdateAvailable) {
|
|
377
|
-
// For complex ranges, preserve the original format
|
|
378
|
-
return latest;
|
|
379
|
-
}
|
|
380
|
-
return null;
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
// Simple range - parse normally
|
|
384
|
-
const rangeInfo = this._parseVersionRange(currentRange);
|
|
385
|
-
|
|
386
|
-
if (!rangeInfo) {
|
|
387
|
-
return null; // Can't parse, skip
|
|
388
|
-
}
|
|
389
|
-
|
|
390
|
-
// Check if update is available and compatible
|
|
391
|
-
const isUpdateAvailable = this._isUpdateAvailable(rangeInfo, latestParsed);
|
|
392
|
-
|
|
393
|
-
if (isUpdateAvailable) {
|
|
394
|
-
// Preserve the original prefix
|
|
395
|
-
return rangeInfo.prefix + latest;
|
|
396
|
-
}
|
|
397
|
-
|
|
398
|
-
return null;
|
|
399
|
-
}
|
|
400
|
-
|
|
401
|
-
/**
|
|
402
|
-
* Parse a version string into components including pre-release and build metadata
|
|
403
|
-
* @param {string} version - Version string (e.g., "4.17.1", "1.0.0-alpha.1", "1.0.0+build.123")
|
|
404
|
-
* @returns {Object|null} Parsed version or null
|
|
405
|
-
* @private
|
|
406
|
-
*/
|
|
407
|
-
_parseVersion(version) {
|
|
408
|
-
// Match: major.minor.patch[-prerelease][+build]
|
|
409
|
-
// Pre-release and build are optional
|
|
410
|
-
const pattern = /^(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?(?:\+([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?$/;
|
|
411
|
-
const match = pattern.exec(version);
|
|
412
|
-
|
|
413
|
-
if (!match) {
|
|
414
|
-
// Fallback: try simple X.Y.Z pattern without pre-release/build
|
|
415
|
-
const simpleMatch = version.match(/^(\d+)\.(\d+)\.(\d+)/);
|
|
416
|
-
if (simpleMatch) {
|
|
417
|
-
return {
|
|
418
|
-
major: parseInt(simpleMatch[1], 10),
|
|
419
|
-
minor: parseInt(simpleMatch[2], 10),
|
|
420
|
-
patch: parseInt(simpleMatch[3], 10),
|
|
421
|
-
prerelease: null,
|
|
422
|
-
build: null
|
|
423
|
-
};
|
|
424
|
-
}
|
|
425
|
-
return null;
|
|
426
|
-
}
|
|
427
|
-
|
|
428
|
-
return {
|
|
429
|
-
major: parseInt(match[1], 10),
|
|
430
|
-
minor: parseInt(match[2], 10),
|
|
431
|
-
patch: parseInt(match[3], 10),
|
|
432
|
-
prerelease: match[4] ? match[4].split('.') : null,
|
|
433
|
-
build: match[5] || null
|
|
434
|
-
};
|
|
435
|
-
}
|
|
436
|
-
|
|
437
|
-
/**
|
|
438
|
-
* Compare two versions according to semver rules
|
|
439
|
-
* Returns: < 0 if v1 < v2, 0 if v1 === v2, > 0 if v1 > v2
|
|
440
|
-
* Handles pre-release versions correctly:
|
|
441
|
-
* - 1.0.0 > 1.0.0-alpha (release > pre-release)
|
|
442
|
-
* - 1.0.0-alpha < 1.0.0-beta (lexical comparison)
|
|
443
|
-
* - 1.0.0-1 < 1.0.0-2 (numeric comparison)
|
|
444
|
-
* @param {Object} v1 - First version
|
|
445
|
-
* @param {Object} v2 - Second version
|
|
446
|
-
* @returns {number} Comparison result
|
|
447
|
-
* @private
|
|
448
|
-
*/
|
|
449
|
-
_compareVersions(v1, v2) {
|
|
450
|
-
// Compare major.minor.patch first
|
|
451
|
-
if (v1.major !== v2.major) return v1.major - v2.major;
|
|
452
|
-
if (v1.minor !== v2.minor) return v1.minor - v2.minor;
|
|
453
|
-
if (v1.patch !== v2.patch) return v1.patch - v2.patch;
|
|
454
|
-
|
|
455
|
-
// When major.minor.patch are equal, check pre-release
|
|
456
|
-
// According to semver spec:
|
|
457
|
-
// 1. Release version (no prerelease) > prerelease version
|
|
458
|
-
// 2. If both have prerelease, compare identifiers
|
|
459
|
-
|
|
460
|
-
if (!v1.prerelease && !v2.prerelease) {
|
|
461
|
-
// Both are release versions, equal
|
|
462
|
-
return 0;
|
|
463
|
-
}
|
|
464
|
-
|
|
465
|
-
if (!v1.prerelease && v2.prerelease) {
|
|
466
|
-
// v1 is release, v2 is pre-release → v1 > v2
|
|
467
|
-
return 1;
|
|
468
|
-
}
|
|
469
|
-
|
|
470
|
-
if (v1.prerelease && !v2.prerelease) {
|
|
471
|
-
// v1 is pre-release, v2 is release → v1 < v2
|
|
472
|
-
return -1;
|
|
473
|
-
}
|
|
474
|
-
|
|
475
|
-
// Both have pre-release, compare them
|
|
476
|
-
return this._comparePrerelease(v1.prerelease, v2.prerelease);
|
|
477
|
-
}
|
|
478
|
-
|
|
479
|
-
/**
|
|
480
|
-
* Compare pre-release version identifiers according to semver spec
|
|
481
|
-
* Identifiers are compared as:
|
|
482
|
-
* 1. Numeric identifiers are compared numerically
|
|
483
|
-
* 2. Alphanumeric identifiers are compared lexically (ASCII sort)
|
|
484
|
-
* 3. Numeric identifiers have lower precedence than alphanumeric
|
|
485
|
-
* 4. Larger set of identifiers has higher precedence if all preceding are equal
|
|
486
|
-
* @param {Array<string>} pre1 - First pre-release identifiers
|
|
487
|
-
* @param {Array<string>} pre2 - Second pre-release identifiers
|
|
488
|
-
* @returns {number} Comparison result
|
|
489
|
-
* @private
|
|
490
|
-
*/
|
|
491
|
-
_comparePrerelease(pre1, pre2) {
|
|
492
|
-
const len = Math.max(pre1.length, pre2.length);
|
|
493
|
-
|
|
494
|
-
for (let i = 0; i < len; i++) {
|
|
495
|
-
// If one pre-release has fewer identifiers, it has lower precedence
|
|
496
|
-
if (i >= pre1.length) return -1; // pre1 is shorter, pre1 < pre2
|
|
497
|
-
if (i >= pre2.length) return 1; // pre2 is shorter, pre1 > pre2
|
|
498
|
-
|
|
499
|
-
const part1 = pre1[i];
|
|
500
|
-
const part2 = pre2[i];
|
|
501
|
-
|
|
502
|
-
// Check if parts are numeric
|
|
503
|
-
const num1 = /^\d+$/.test(part1) ? parseInt(part1, 10) : null;
|
|
504
|
-
const num2 = /^\d+$/.test(part2) ? parseInt(part2, 10) : null;
|
|
505
|
-
|
|
506
|
-
// Both numeric: compare numerically
|
|
507
|
-
if (num1 !== null && num2 !== null) {
|
|
508
|
-
if (num1 !== num2) return num1 - num2;
|
|
509
|
-
continue;
|
|
510
|
-
}
|
|
511
|
-
|
|
512
|
-
// One numeric, one alphanumeric: numeric has lower precedence
|
|
513
|
-
if (num1 !== null && num2 === null) return -1;
|
|
514
|
-
if (num1 === null && num2 !== null) return 1;
|
|
515
|
-
|
|
516
|
-
// Both alphanumeric: compare lexically
|
|
517
|
-
if (part1 < part2) return -1;
|
|
518
|
-
if (part1 > part2) return 1;
|
|
519
|
-
}
|
|
520
|
-
|
|
521
|
-
// All identifiers equal
|
|
522
|
-
return 0;
|
|
523
|
-
}
|
|
524
|
-
|
|
525
|
-
/**
|
|
526
|
-
* Parse version range into components
|
|
527
|
-
* @param {string} range - Version range (e.g., "^4.17.1", "~4.17.1", "<5.0.0", "4.x", "4.*")
|
|
528
|
-
* @returns {Object|null} Parsed range or null
|
|
529
|
-
* @private
|
|
530
|
-
*/
|
|
531
|
-
_parseVersionRange(range) {
|
|
532
|
-
const trimmed = range.trim();
|
|
533
|
-
|
|
534
|
-
// Check for X-ranges first: 4.x, 4.*, 4.17.x, 4.17.*, or just 4
|
|
535
|
-
// X-ranges use 'x', '*', or missing parts as wildcards
|
|
536
|
-
const xRangePattern = /^(\d+|\*|x)(\.(\d+|\*|x))?(\.(\d+|\*|x))?$/i;
|
|
537
|
-
const xMatch = xRangePattern.exec(trimmed);
|
|
538
|
-
|
|
539
|
-
if (xMatch) {
|
|
540
|
-
const majorStr = xMatch[1];
|
|
541
|
-
const minorStr = xMatch[3];
|
|
542
|
-
const patchStr = xMatch[5];
|
|
543
|
-
|
|
544
|
-
// Check if any part is wildcard or missing (making it an X-range)
|
|
545
|
-
const isXRange =
|
|
546
|
-
majorStr === '*' || majorStr.toLowerCase() === 'x' ||
|
|
547
|
-
minorStr === undefined || minorStr === '*' || minorStr.toLowerCase() === 'x' ||
|
|
548
|
-
patchStr === undefined || patchStr === '*' || patchStr.toLowerCase() === 'x';
|
|
549
|
-
|
|
550
|
-
if (isXRange) {
|
|
551
|
-
return {
|
|
552
|
-
prefix: '',
|
|
553
|
-
operator: 'x-range',
|
|
554
|
-
major: (majorStr === '*' || majorStr.toLowerCase() === 'x') ? null : parseInt(majorStr, 10),
|
|
555
|
-
minor: (!minorStr || minorStr === '*' || minorStr.toLowerCase() === 'x') ? null : parseInt(minorStr, 10),
|
|
556
|
-
patch: (!patchStr || patchStr === '*' || patchStr.toLowerCase() === 'x') ? null : parseInt(patchStr, 10),
|
|
557
|
-
original: range
|
|
558
|
-
};
|
|
559
|
-
}
|
|
560
|
-
}
|
|
561
|
-
|
|
562
|
-
// Extract prefix and version for other operators
|
|
563
|
-
let prefix = '';
|
|
564
|
-
let version = trimmed;
|
|
565
|
-
let operator = '=';
|
|
566
|
-
|
|
567
|
-
if (trimmed.startsWith('^')) {
|
|
568
|
-
prefix = '^';
|
|
569
|
-
version = trimmed.slice(1);
|
|
570
|
-
operator = '^';
|
|
571
|
-
} else if (trimmed.startsWith('~')) {
|
|
572
|
-
prefix = '~';
|
|
573
|
-
version = trimmed.slice(1);
|
|
574
|
-
operator = '~';
|
|
575
|
-
} else if (trimmed.startsWith('>=')) {
|
|
576
|
-
prefix = '>=';
|
|
577
|
-
version = trimmed.slice(2).trim();
|
|
578
|
-
operator = '>=';
|
|
579
|
-
} else if (trimmed.startsWith('>')) {
|
|
580
|
-
prefix = '>';
|
|
581
|
-
version = trimmed.slice(1).trim();
|
|
582
|
-
operator = '>';
|
|
583
|
-
} else if (trimmed.startsWith('<=')) {
|
|
584
|
-
prefix = '<=';
|
|
585
|
-
version = trimmed.slice(2).trim();
|
|
586
|
-
operator = '<=';
|
|
587
|
-
} else if (trimmed.startsWith('<')) {
|
|
588
|
-
prefix = '<';
|
|
589
|
-
version = trimmed.slice(1).trim();
|
|
590
|
-
operator = '<';
|
|
591
|
-
}
|
|
592
|
-
|
|
593
|
-
// Parse version X.Y.Z (including pre-release and build)
|
|
594
|
-
const parsed = this._parseVersion(version);
|
|
595
|
-
|
|
596
|
-
if (!parsed) {
|
|
597
|
-
return null;
|
|
598
|
-
}
|
|
599
|
-
|
|
600
|
-
return {
|
|
601
|
-
prefix,
|
|
602
|
-
operator,
|
|
603
|
-
major: parsed.major,
|
|
604
|
-
minor: parsed.minor,
|
|
605
|
-
patch: parsed.patch,
|
|
606
|
-
prerelease: parsed.prerelease,
|
|
607
|
-
build: parsed.build,
|
|
608
|
-
original: range
|
|
609
|
-
};
|
|
610
|
-
}
|
|
611
|
-
|
|
612
|
-
/**
|
|
613
|
-
* Check if update is available and compatible with range
|
|
614
|
-
* @param {Object} rangeInfo - Parsed range information
|
|
615
|
-
* @param {Object} latest - Parsed latest version
|
|
616
|
-
* @returns {boolean} True if update available
|
|
617
|
-
* @private
|
|
618
|
-
*/
|
|
619
|
-
_isUpdateAvailable(rangeInfo, latest) {
|
|
620
|
-
const current = {
|
|
621
|
-
major: rangeInfo.major,
|
|
622
|
-
minor: rangeInfo.minor,
|
|
623
|
-
patch: rangeInfo.patch,
|
|
624
|
-
prerelease: rangeInfo.prerelease || null,
|
|
625
|
-
build: rangeInfo.build || null
|
|
626
|
-
};
|
|
627
|
-
|
|
628
|
-
// Check based on operator
|
|
629
|
-
switch (rangeInfo.operator) {
|
|
630
|
-
case '^':
|
|
631
|
-
return this._isCaretUpdateAvailable(current, latest);
|
|
632
|
-
|
|
633
|
-
case '~':
|
|
634
|
-
return this._isTildeUpdateAvailable(current, latest);
|
|
635
|
-
|
|
636
|
-
case '>=':
|
|
637
|
-
case '>':
|
|
638
|
-
return this._isSimpleUpdateAvailable(current, latest);
|
|
639
|
-
|
|
640
|
-
case '<':
|
|
641
|
-
case '<=':
|
|
642
|
-
return this._isLessThanUpdateAvailable(rangeInfo, latest);
|
|
643
|
-
|
|
644
|
-
case 'x-range':
|
|
645
|
-
return this._isXRangeUpdateAvailable(rangeInfo, latest);
|
|
646
|
-
|
|
647
|
-
case '=':
|
|
648
|
-
default:
|
|
649
|
-
return this._isExactUpdateAvailable(current, latest);
|
|
650
|
-
}
|
|
651
|
-
}
|
|
652
|
-
|
|
653
|
-
/**
|
|
654
|
-
* Check if update is available for caret range (^)
|
|
655
|
-
* Handles special cases:
|
|
656
|
-
* - ^0.0.X → Only patch updates in 0.0.*
|
|
657
|
-
* - ^0.X.Y → Only patch updates in 0.X.*
|
|
658
|
-
* - ^X.Y.Z → Minor and patch updates in X.*.*
|
|
659
|
-
* Also handles pre-release versions correctly
|
|
660
|
-
* @private
|
|
661
|
-
*/
|
|
662
|
-
_isCaretUpdateAvailable(current, latest) {
|
|
663
|
-
// First check if latest is actually greater than current
|
|
664
|
-
const cmp = this._compareVersions(latest, current);
|
|
665
|
-
if (cmp <= 0) {
|
|
666
|
-
// latest is not greater than current
|
|
667
|
-
return false;
|
|
668
|
-
}
|
|
669
|
-
|
|
670
|
-
// ^0.0.X → Only patch updates in 0.0.*
|
|
671
|
-
if (current.major === 0 && current.minor === 0) {
|
|
672
|
-
return latest.major === 0 && latest.minor === 0;
|
|
673
|
-
}
|
|
674
|
-
|
|
675
|
-
// ^0.X.Y → Only patch updates in 0.X.*
|
|
676
|
-
if (current.major === 0) {
|
|
677
|
-
return latest.major === 0 && latest.minor === current.minor;
|
|
678
|
-
}
|
|
679
|
-
|
|
680
|
-
// ^X.Y.Z → Any minor/patch update in X.*.*
|
|
681
|
-
return latest.major === current.major;
|
|
682
|
-
}
|
|
683
|
-
|
|
684
|
-
/**
|
|
685
|
-
* Check if update is available for tilde range (~)
|
|
686
|
-
* ~X.Y.Z → Only patch updates in X.Y.*
|
|
687
|
-
* Also handles pre-release versions correctly
|
|
688
|
-
* @private
|
|
689
|
-
*/
|
|
690
|
-
_isTildeUpdateAvailable(current, latest) {
|
|
691
|
-
// First check if latest is actually greater than current
|
|
692
|
-
const cmp = this._compareVersions(latest, current);
|
|
693
|
-
if (cmp <= 0) {
|
|
694
|
-
return false;
|
|
695
|
-
}
|
|
696
|
-
|
|
697
|
-
// Must be same major and minor
|
|
698
|
-
return latest.major === current.major && latest.minor === current.minor;
|
|
699
|
-
}
|
|
700
|
-
|
|
701
|
-
/**
|
|
702
|
-
* Check if update is available for simple comparison (>, >=)
|
|
703
|
-
* Also handles pre-release versions correctly
|
|
704
|
-
* @private
|
|
705
|
-
*/
|
|
706
|
-
_isSimpleUpdateAvailable(current, latest) {
|
|
707
|
-
// Use proper version comparison that handles pre-release
|
|
708
|
-
const cmp = this._compareVersions(latest, current);
|
|
709
|
-
return cmp > 0;
|
|
710
|
-
}
|
|
711
|
-
|
|
712
|
-
/**
|
|
713
|
-
* Check if update is available for exact version
|
|
714
|
-
* Suggests update if latest is newer
|
|
715
|
-
* @private
|
|
716
|
-
*/
|
|
717
|
-
_isExactUpdateAvailable(current, latest) {
|
|
718
|
-
return this._isSimpleUpdateAvailable(current, latest);
|
|
719
|
-
}
|
|
720
|
-
|
|
721
|
-
/**
|
|
722
|
-
* Check if update is available for less than operators (<, <=)
|
|
723
|
-
* <X.Y.Z → latest must be < range
|
|
724
|
-
* <=X.Y.Z → latest must be <= range
|
|
725
|
-
* Also handles pre-release versions correctly
|
|
726
|
-
* @param {Object} rangeInfo - Parsed range information
|
|
727
|
-
* @param {Object} latest - Parsed latest version
|
|
728
|
-
* @returns {boolean} True if update satisfies constraint
|
|
729
|
-
* @private
|
|
730
|
-
*/
|
|
731
|
-
_isLessThanUpdateAvailable(rangeInfo, latest) {
|
|
732
|
-
// Use proper version comparison that handles pre-release
|
|
733
|
-
const cmp = this._compareVersions(latest, rangeInfo);
|
|
734
|
-
|
|
735
|
-
if (rangeInfo.operator === '<') {
|
|
736
|
-
// latest must be < range
|
|
737
|
-
return cmp < 0;
|
|
738
|
-
} else if (rangeInfo.operator === '<=') {
|
|
739
|
-
// latest must be <= range
|
|
740
|
-
return cmp <= 0;
|
|
741
|
-
}
|
|
742
|
-
return false;
|
|
743
|
-
}
|
|
744
|
-
|
|
745
|
-
/**
|
|
746
|
-
* Check if update is available for X-ranges (4.x, 4.*, 4.17.x, etc.)
|
|
747
|
-
* X-ranges match any version within the specified parts
|
|
748
|
-
* 4.x or 4.* → any version 4.Y.Z
|
|
749
|
-
* 4.17.x or 4.17.* → any version 4.17.Z
|
|
750
|
-
* *.*.* → any version
|
|
751
|
-
* @param {Object} rangeInfo - Parsed range information
|
|
752
|
-
* @param {Object} latest - Parsed latest version
|
|
753
|
-
* @returns {boolean} True if update is within range
|
|
754
|
-
* @private
|
|
755
|
-
*/
|
|
756
|
-
_isXRangeUpdateAvailable(rangeInfo, latest) {
|
|
757
|
-
// Check major version if specified
|
|
758
|
-
if (rangeInfo.major !== null && latest.major !== rangeInfo.major) {
|
|
759
|
-
return false;
|
|
760
|
-
}
|
|
761
|
-
|
|
762
|
-
// Check minor version if specified
|
|
763
|
-
if (rangeInfo.minor !== null && latest.minor !== rangeInfo.minor) {
|
|
764
|
-
return false;
|
|
765
|
-
}
|
|
766
|
-
|
|
767
|
-
// Check patch version if specified
|
|
768
|
-
if (rangeInfo.patch !== null && latest.patch !== rangeInfo.patch) {
|
|
769
|
-
return false;
|
|
770
|
-
}
|
|
771
|
-
|
|
772
|
-
// All specified parts match, update is within range
|
|
773
|
-
return true;
|
|
774
|
-
}
|
|
775
|
-
|
|
776
|
-
/**
|
|
777
|
-
* Check if a range string is a complex range (contains AND/OR operators)
|
|
778
|
-
* Complex ranges include:
|
|
779
|
-
* - OR ranges: "^4.0.0 || ^5.0.0"
|
|
780
|
-
* - AND ranges: ">=4.0.0 <5.0.0" (space-separated, multiple constraints)
|
|
781
|
-
* @param {string} range - Version range string
|
|
782
|
-
* @returns {boolean} True if complex range
|
|
783
|
-
* @private
|
|
784
|
-
*/
|
|
785
|
-
_isComplexRange(range) {
|
|
786
|
-
// Check for OR operator
|
|
787
|
-
if (range.includes('||')) {
|
|
788
|
-
return true;
|
|
789
|
-
}
|
|
790
|
-
|
|
791
|
-
// Check for AND (multiple space-separated ranges)
|
|
792
|
-
// Need to detect patterns like ">=4.0.0 <5.0.0"
|
|
793
|
-
// But NOT "^4.0.0" or "~4.0.0" (single ranges with spaces after)
|
|
794
|
-
const trimmed = range.trim();
|
|
795
|
-
|
|
796
|
-
// Remove single operator prefixes to see what's left
|
|
797
|
-
if (trimmed.startsWith('^') || trimmed.startsWith('~')) {
|
|
798
|
-
return false; // Single caret or tilde range
|
|
799
|
-
}
|
|
800
|
-
|
|
801
|
-
// Split by whitespace and check if there are multiple parts
|
|
802
|
-
const parts = trimmed.split(/\s+/).filter(p => p.length > 0);
|
|
803
|
-
|
|
804
|
-
// If we have multiple parts, it might be a complex AND range
|
|
805
|
-
// Examples: [">=4.0.0", "<5.0.0"], [">1.0.0", "<2.0.0"]
|
|
806
|
-
if (parts.length > 1) {
|
|
807
|
-
// Check if each part looks like a range operator
|
|
808
|
-
const rangeOperators = /^(>=?|<=?|\^|~|[0-9])/;
|
|
809
|
-
return parts.every(part => rangeOperators.test(part));
|
|
810
|
-
}
|
|
811
|
-
|
|
812
|
-
return false;
|
|
813
|
-
}
|
|
814
|
-
|
|
815
|
-
/**
|
|
816
|
-
* Parse a complex range expression into a structured format
|
|
817
|
-
* Handles:
|
|
818
|
-
* - OR: "^4.0.0 || ^5.0.0" → {type: 'or', ranges: [...]}
|
|
819
|
-
* - AND: ">=4.0.0 <5.0.0" → {type: 'and', ranges: [...]}
|
|
820
|
-
* - Simple: "^4.0.0" → {type: 'simple', range: {...}}
|
|
821
|
-
* @param {string} range - Complex range string
|
|
822
|
-
* @returns {Object} Parsed complex range structure
|
|
823
|
-
* @private
|
|
824
|
-
*/
|
|
825
|
-
_parseComplexRange(range) {
|
|
826
|
-
// Split by OR first (|| has precedence)
|
|
827
|
-
if (range.includes('||')) {
|
|
828
|
-
const orParts = range.split('||').map(p => p.trim());
|
|
829
|
-
return {
|
|
830
|
-
type: 'or',
|
|
831
|
-
ranges: orParts.map(part => this._parseComplexRange(part))
|
|
832
|
-
};
|
|
833
|
-
}
|
|
834
|
-
|
|
835
|
-
// Split by AND (space-separated, no || present)
|
|
836
|
-
const andParts = range.trim().split(/\s+/).filter(p => p.length > 0);
|
|
837
|
-
|
|
838
|
-
if (andParts.length > 1) {
|
|
839
|
-
return {
|
|
840
|
-
type: 'and',
|
|
841
|
-
ranges: andParts.map(part => this._parseVersionRange(part))
|
|
842
|
-
};
|
|
843
|
-
}
|
|
844
|
-
|
|
845
|
-
// Simple range
|
|
846
|
-
return {
|
|
847
|
-
type: 'simple',
|
|
848
|
-
range: this._parseVersionRange(range)
|
|
849
|
-
};
|
|
850
|
-
}
|
|
851
|
-
|
|
852
|
-
/**
|
|
853
|
-
* Check if a version satisfies a single range
|
|
854
|
-
* @param {Object} rangeInfo - Parsed range information
|
|
855
|
-
* @param {Object} version - Parsed version to check
|
|
856
|
-
* @returns {boolean} True if version satisfies range
|
|
857
|
-
* @private
|
|
858
|
-
*/
|
|
859
|
-
_satisfiesRange(rangeInfo, version) {
|
|
860
|
-
if (!rangeInfo || !version) {
|
|
861
|
-
return false;
|
|
862
|
-
}
|
|
863
|
-
|
|
864
|
-
// Use the existing _isUpdateAvailable logic which handles all operators
|
|
865
|
-
return this._isUpdateAvailable(rangeInfo, version);
|
|
866
|
-
}
|
|
867
|
-
|
|
868
|
-
/**
|
|
869
|
-
* Check if a version satisfies a complex range expression
|
|
870
|
-
* Handles AND/OR logic recursively
|
|
871
|
-
* @param {Object} complexRange - Parsed complex range structure
|
|
872
|
-
* @param {Object} version - Parsed version to check
|
|
873
|
-
* @returns {boolean} True if version satisfies the complex range
|
|
874
|
-
* @private
|
|
875
|
-
*/
|
|
876
|
-
_satisfiesComplexRange(complexRange, version) {
|
|
877
|
-
if (!complexRange || !version) {
|
|
878
|
-
return false;
|
|
879
|
-
}
|
|
880
|
-
|
|
881
|
-
switch (complexRange.type) {
|
|
882
|
-
case 'simple':
|
|
883
|
-
return this._satisfiesRange(complexRange.range, version);
|
|
884
|
-
|
|
885
|
-
case 'and':
|
|
886
|
-
// ALL ranges must be satisfied
|
|
887
|
-
return complexRange.ranges.every(range => this._satisfiesRange(range, version));
|
|
888
|
-
|
|
889
|
-
case 'or':
|
|
890
|
-
// AT LEAST ONE range must be satisfied
|
|
891
|
-
return complexRange.ranges.some(range => this._satisfiesComplexRange(range, version));
|
|
892
|
-
|
|
893
|
-
default:
|
|
894
|
-
return false;
|
|
895
|
-
}
|
|
896
|
-
}
|
|
897
|
-
|
|
898
|
-
/**
|
|
899
|
-
* Check dependencies in batches to avoid overwhelming the registry
|
|
900
|
-
* @param {Object} dependencies - Map of package names to versions
|
|
901
|
-
* @returns {Promise<Object>} Map of packages with available updates
|
|
902
|
-
* @private
|
|
903
|
-
*/
|
|
904
|
-
async _checkDependencies(dependencies) {
|
|
905
|
-
const updates = {};
|
|
906
|
-
const entries = Object.entries(dependencies);
|
|
907
|
-
|
|
908
|
-
// Process in batches
|
|
909
|
-
for (let i = 0; i < entries.length; i += RESOLVER_CONFIG.MAX_CONCURRENT_CHECKS) {
|
|
910
|
-
const batch = entries.slice(i, i + RESOLVER_CONFIG.MAX_CONCURRENT_CHECKS);
|
|
911
|
-
|
|
912
|
-
const promises = batch.map(async ([pkg, range]) => {
|
|
913
|
-
try {
|
|
914
|
-
const latest = await this._getLatestCompatibleVersion(pkg, range);
|
|
915
|
-
|
|
916
|
-
if (latest) {
|
|
917
|
-
// Preserve the range prefix (^, ~, etc.)
|
|
918
|
-
const prefix = range.match(/^[\^~]/)?.[0] || '^';
|
|
919
|
-
return { pkg, newVersion: `${prefix}${latest}`, oldVersion: range };
|
|
920
|
-
}
|
|
921
|
-
|
|
922
|
-
return null;
|
|
923
|
-
} catch (error) {
|
|
924
|
-
this.logger?.error(`Error checking ${pkg}:`, error.message);
|
|
925
|
-
return null;
|
|
926
|
-
}
|
|
927
|
-
});
|
|
928
|
-
|
|
929
|
-
const results = await Promise.all(promises);
|
|
930
|
-
|
|
931
|
-
results.forEach(result => {
|
|
932
|
-
if (result) {
|
|
933
|
-
updates[result.pkg] = result.newVersion;
|
|
934
|
-
}
|
|
935
|
-
});
|
|
936
|
-
}
|
|
937
|
-
|
|
938
|
-
return updates;
|
|
939
|
-
}
|
|
940
|
-
|
|
941
|
-
/**
|
|
942
|
-
* Execute tool with parsed parameters
|
|
943
|
-
* @param {Object} params - Parsed parameters
|
|
944
|
-
* @param {Object} context - Execution context
|
|
945
|
-
* @returns {Promise<Object>} Execution result
|
|
946
|
-
*/
|
|
947
|
-
async execute(params, context = {}) {
|
|
948
|
-
try {
|
|
949
|
-
// Validate parameters
|
|
950
|
-
this._validateParameters(params);
|
|
951
|
-
|
|
952
|
-
const { path: targetPath, mode, includeDev } = params;
|
|
953
|
-
const { projectDir, agentId, directoryAccess } = context;
|
|
954
|
-
|
|
955
|
-
// Resolve and validate path
|
|
956
|
-
const resolvedPath = this._resolveAndValidatePath(targetPath, context);
|
|
957
|
-
const pkgPath = path.join(resolvedPath, 'package.json');
|
|
958
|
-
|
|
959
|
-
this.logger?.info('Dependency resolver executing', {
|
|
960
|
-
mode,
|
|
961
|
-
resolvedPath,
|
|
962
|
-
includeDev,
|
|
963
|
-
agentId
|
|
964
|
-
});
|
|
965
|
-
|
|
966
|
-
const output = [];
|
|
967
|
-
output.push(`🔍 Checking dependencies in: ${resolvedPath}`);
|
|
968
|
-
output.push(`Mode: ${mode}`);
|
|
969
|
-
|
|
970
|
-
// Check if package.json exists
|
|
971
|
-
try {
|
|
972
|
-
await fs.access(pkgPath);
|
|
973
|
-
} catch {
|
|
974
|
-
return {
|
|
975
|
-
success: false,
|
|
976
|
-
error: `No package.json found at: ${pkgPath}`,
|
|
977
|
-
output: output.join('\n')
|
|
978
|
-
};
|
|
979
|
-
}
|
|
980
|
-
|
|
981
|
-
// Read package.json
|
|
982
|
-
output.push('\n📦 Reading package.json...');
|
|
983
|
-
const pkgContent = await fs.readFile(pkgPath, 'utf-8');
|
|
984
|
-
const pkgData = JSON.parse(pkgContent);
|
|
985
|
-
|
|
986
|
-
// Collect dependencies
|
|
987
|
-
const allDeps = { ...pkgData.dependencies };
|
|
988
|
-
|
|
989
|
-
if (includeDev && pkgData.devDependencies) {
|
|
990
|
-
Object.assign(allDeps, pkgData.devDependencies);
|
|
991
|
-
}
|
|
992
|
-
|
|
993
|
-
if (Object.keys(allDeps).length === 0) {
|
|
994
|
-
return {
|
|
995
|
-
success: true,
|
|
996
|
-
mode,
|
|
997
|
-
message: 'No dependencies found in package.json',
|
|
998
|
-
statistics: {
|
|
999
|
-
totalDependencies: 0,
|
|
1000
|
-
updatesAvailable: 0,
|
|
1001
|
-
updatesApplied: 0,
|
|
1002
|
-
errors: 0
|
|
1003
|
-
},
|
|
1004
|
-
output: output.join('\n')
|
|
1005
|
-
};
|
|
1006
|
-
}
|
|
1007
|
-
|
|
1008
|
-
// Safety check
|
|
1009
|
-
if (Object.keys(allDeps).length > RESOLVER_CONFIG.MAX_DEPENDENCIES) {
|
|
1010
|
-
return {
|
|
1011
|
-
success: false,
|
|
1012
|
-
error: `Too many dependencies (${Object.keys(allDeps).length}), max allowed: ${RESOLVER_CONFIG.MAX_DEPENDENCIES}`,
|
|
1013
|
-
output: output.join('\n')
|
|
1014
|
-
};
|
|
1015
|
-
}
|
|
1016
|
-
|
|
1017
|
-
output.push(`📊 Found ${Object.keys(allDeps).length} dependencies to check`);
|
|
1018
|
-
output.push('🌐 Querying npm registry for updates...');
|
|
1019
|
-
|
|
1020
|
-
// Check for updates
|
|
1021
|
-
const updates = await this._checkDependencies(allDeps);
|
|
1022
|
-
|
|
1023
|
-
output.push(`\n✅ Registry check complete`);
|
|
1024
|
-
output.push(`📈 Updates available: ${Object.keys(updates).length}`);
|
|
1025
|
-
|
|
1026
|
-
if (Object.keys(updates).length > 0) {
|
|
1027
|
-
output.push('\n📋 Available updates:');
|
|
1028
|
-
for (const [pkg, newVersion] of Object.entries(updates)) {
|
|
1029
|
-
const oldVersion = allDeps[pkg];
|
|
1030
|
-
output.push(` • ${pkg}: ${oldVersion} → ${newVersion}`);
|
|
1031
|
-
}
|
|
1032
|
-
} else {
|
|
1033
|
-
output.push('\n🎉 All dependencies are up-to-date!');
|
|
1034
|
-
}
|
|
1035
|
-
|
|
1036
|
-
// Handle modes
|
|
1037
|
-
if (mode === 'check') {
|
|
1038
|
-
// Check mode - just report
|
|
1039
|
-
if (Object.keys(updates).length > 0) {
|
|
1040
|
-
output.push('\n💡 Run with mode="fix" or mode="auto" to apply updates');
|
|
1041
|
-
}
|
|
1042
|
-
|
|
1043
|
-
return {
|
|
1044
|
-
success: true,
|
|
1045
|
-
mode: 'check',
|
|
1046
|
-
message: `Found ${Object.keys(updates).length} package(s) with available updates`,
|
|
1047
|
-
statistics: {
|
|
1048
|
-
totalDependencies: Object.keys(allDeps).length,
|
|
1049
|
-
updatesAvailable: Object.keys(updates).length,
|
|
1050
|
-
updatesApplied: 0,
|
|
1051
|
-
errors: 0
|
|
1052
|
-
},
|
|
1053
|
-
updates,
|
|
1054
|
-
output: output.join('\n')
|
|
1055
|
-
};
|
|
1056
|
-
}
|
|
1057
|
-
|
|
1058
|
-
// Fix or auto mode - apply updates
|
|
1059
|
-
if ((mode === 'fix' || mode === 'auto') && Object.keys(updates).length > 0) {
|
|
1060
|
-
// Create backup
|
|
1061
|
-
output.push('\n💾 Creating backup of package.json...');
|
|
1062
|
-
const backupPath = await this._createBackup(pkgPath);
|
|
1063
|
-
|
|
1064
|
-
if (backupPath) {
|
|
1065
|
-
output.push(`✅ Backup created: ${path.basename(backupPath)}`);
|
|
1066
|
-
} else {
|
|
1067
|
-
output.push('⚠️ Backup creation failed, continuing anyway...');
|
|
1068
|
-
}
|
|
1069
|
-
|
|
1070
|
-
// Update package.json
|
|
1071
|
-
output.push('\n🛠 Updating package.json...');
|
|
1072
|
-
|
|
1073
|
-
for (const [pkg, newVersion] of Object.entries(updates)) {
|
|
1074
|
-
if (pkgData.dependencies?.[pkg]) {
|
|
1075
|
-
pkgData.dependencies[pkg] = newVersion;
|
|
1076
|
-
}
|
|
1077
|
-
if (pkgData.devDependencies?.[pkg]) {
|
|
1078
|
-
pkgData.devDependencies[pkg] = newVersion;
|
|
1079
|
-
}
|
|
1080
|
-
}
|
|
1081
|
-
|
|
1082
|
-
// Write updated package.json
|
|
1083
|
-
await fs.writeFile(pkgPath, JSON.stringify(pkgData, null, 2) + '\n');
|
|
1084
|
-
output.push('✅ package.json updated');
|
|
1085
|
-
|
|
1086
|
-
// Run npm install
|
|
1087
|
-
output.push('\n📥 Installing dependencies (this may take a while)...');
|
|
1088
|
-
|
|
1089
|
-
try {
|
|
1090
|
-
const { stdout, stderr } = await exec('npm install', {
|
|
1091
|
-
cwd: resolvedPath,
|
|
1092
|
-
timeout: RESOLVER_CONFIG.NPM_COMMAND_TIMEOUT,
|
|
1093
|
-
maxBuffer: 1024 * 1024 * 10 // 10MB buffer
|
|
1094
|
-
});
|
|
1095
|
-
|
|
1096
|
-
if (stdout) {
|
|
1097
|
-
// Only show summary, not full output
|
|
1098
|
-
const lines = stdout.trim().split('\n');
|
|
1099
|
-
if (lines.length > 10) {
|
|
1100
|
-
output.push(' ' + lines.slice(-5).join('\n '));
|
|
1101
|
-
} else {
|
|
1102
|
-
output.push(' ' + stdout.trim());
|
|
1103
|
-
}
|
|
1104
|
-
}
|
|
1105
|
-
|
|
1106
|
-
if (stderr && !stderr.includes('npm WARN')) {
|
|
1107
|
-
output.push(`⚠️ ${stderr.trim()}`);
|
|
1108
|
-
}
|
|
1109
|
-
|
|
1110
|
-
output.push('✅ Installation complete');
|
|
1111
|
-
|
|
1112
|
-
// Show installed versions
|
|
1113
|
-
try {
|
|
1114
|
-
const { stdout: lsOutput } = await exec('npm ls --depth=0 --json', {
|
|
1115
|
-
cwd: resolvedPath,
|
|
1116
|
-
timeout: 30000
|
|
1117
|
-
});
|
|
1118
|
-
|
|
1119
|
-
const lsData = JSON.parse(lsOutput);
|
|
1120
|
-
|
|
1121
|
-
if (lsData.dependencies) {
|
|
1122
|
-
output.push('\n📦 Installed versions:');
|
|
1123
|
-
for (const pkg of Object.keys(updates)) {
|
|
1124
|
-
if (lsData.dependencies[pkg]) {
|
|
1125
|
-
output.push(` • ${pkg}@${lsData.dependencies[pkg].version}`);
|
|
1126
|
-
}
|
|
1127
|
-
}
|
|
1128
|
-
}
|
|
1129
|
-
} catch (lsError) {
|
|
1130
|
-
// npm ls might fail with peer dependency warnings - that's okay
|
|
1131
|
-
this.logger?.debug('npm ls failed:', lsError.message);
|
|
1132
|
-
}
|
|
1133
|
-
|
|
1134
|
-
return {
|
|
1135
|
-
success: true,
|
|
1136
|
-
mode,
|
|
1137
|
-
message: `Successfully updated ${Object.keys(updates).length} package(s)`,
|
|
1138
|
-
statistics: {
|
|
1139
|
-
totalDependencies: Object.keys(allDeps).length,
|
|
1140
|
-
updatesAvailable: Object.keys(updates).length,
|
|
1141
|
-
updatesApplied: Object.keys(updates).length,
|
|
1142
|
-
errors: 0
|
|
1143
|
-
},
|
|
1144
|
-
updates,
|
|
1145
|
-
backupCreated: backupPath !== null,
|
|
1146
|
-
backupPath,
|
|
1147
|
-
output: output.join('\n')
|
|
1148
|
-
};
|
|
1149
|
-
|
|
1150
|
-
} catch (installError) {
|
|
1151
|
-
output.push(`\n❌ npm install failed: ${installError.message}`);
|
|
1152
|
-
|
|
1153
|
-
// Try to restore from backup
|
|
1154
|
-
if (backupPath) {
|
|
1155
|
-
try {
|
|
1156
|
-
await fs.copyFile(backupPath, pkgPath);
|
|
1157
|
-
output.push('🔄 Restored package.json from backup');
|
|
1158
|
-
} catch (restoreError) {
|
|
1159
|
-
output.push('⚠️ Failed to restore backup');
|
|
1160
|
-
}
|
|
1161
|
-
}
|
|
1162
|
-
|
|
1163
|
-
return {
|
|
1164
|
-
success: false,
|
|
1165
|
-
mode,
|
|
1166
|
-
error: `npm install failed: ${installError.message}`,
|
|
1167
|
-
statistics: {
|
|
1168
|
-
totalDependencies: Object.keys(allDeps).length,
|
|
1169
|
-
updatesAvailable: Object.keys(updates).length,
|
|
1170
|
-
updatesApplied: 0,
|
|
1171
|
-
errors: 1
|
|
1172
|
-
},
|
|
1173
|
-
updates,
|
|
1174
|
-
backupCreated: backupPath !== null,
|
|
1175
|
-
output: output.join('\n')
|
|
1176
|
-
};
|
|
1177
|
-
}
|
|
1178
|
-
} else if (mode === 'fix' || mode === 'auto') {
|
|
1179
|
-
// No updates needed
|
|
1180
|
-
output.push('\n✨ No updates needed');
|
|
1181
|
-
|
|
1182
|
-
return {
|
|
1183
|
-
success: true,
|
|
1184
|
-
mode,
|
|
1185
|
-
message: 'All dependencies are up-to-date',
|
|
1186
|
-
statistics: {
|
|
1187
|
-
totalDependencies: Object.keys(allDeps).length,
|
|
1188
|
-
updatesAvailable: 0,
|
|
1189
|
-
updatesApplied: 0,
|
|
1190
|
-
errors: 0
|
|
1191
|
-
},
|
|
1192
|
-
updates: {},
|
|
1193
|
-
output: output.join('\n')
|
|
1194
|
-
};
|
|
1195
|
-
}
|
|
1196
|
-
|
|
1197
|
-
} catch (error) {
|
|
1198
|
-
this.logger?.error('Dependency resolver error:', error);
|
|
1199
|
-
|
|
1200
|
-
return {
|
|
1201
|
-
success: false,
|
|
1202
|
-
error: error.message,
|
|
1203
|
-
statistics: {
|
|
1204
|
-
totalDependencies: 0,
|
|
1205
|
-
updatesAvailable: 0,
|
|
1206
|
-
updatesApplied: 0,
|
|
1207
|
-
errors: 1
|
|
1208
|
-
},
|
|
1209
|
-
output: error.message
|
|
1210
|
-
};
|
|
1211
|
-
}
|
|
1212
|
-
}
|
|
1213
|
-
}
|
|
1214
|
-
|
|
1215
|
-
export default DependencyResolverTool;
|
|
1
|
+
const a0_0x4e9f0a=a0_0x2701;(function(_0x3a4336,_0x5471f8){const _0x5d4aa1=a0_0x2701,_0x14a7b4=_0x3a4336();while(!![]){try{const _0xb5342d=-parseInt(_0x5d4aa1(0x16a))/0x1*(-parseInt(_0x5d4aa1(0x114))/0x2)+-parseInt(_0x5d4aa1(0x167))/0x3*(parseInt(_0x5d4aa1(0x13e))/0x4)+parseInt(_0x5d4aa1(0x124))/0x5+parseInt(_0x5d4aa1(0x170))/0x6*(-parseInt(_0x5d4aa1(0x109))/0x7)+-parseInt(_0x5d4aa1(0x163))/0x8*(parseInt(_0x5d4aa1(0x117))/0x9)+-parseInt(_0x5d4aa1(0x145))/0xa*(parseInt(_0x5d4aa1(0x11a))/0xb)+parseInt(_0x5d4aa1(0x129))/0xc;if(_0xb5342d===_0x5471f8)break;else _0x14a7b4['push'](_0x14a7b4['shift']());}catch(_0x5bdaa9){_0x14a7b4['push'](_0x14a7b4['shift']());}}}(a0_0x246f,0xb894f));import{promises as a0_0x4101c3}from'fs';import a0_0x175bde from'path';function a0_0x2701(_0x3c2500,_0x1b395b){_0x3c2500=_0x3c2500-0xf5;const _0x246f89=a0_0x246f();let _0x270154=_0x246f89[_0x3c2500];if(a0_0x2701['AWmPNt']===undefined){var _0x38f6af=function(_0x3e4118){const _0x46b12e='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';let _0x4101c3='',_0x175bde='';for(let _0x542411=0x0,_0xbd4818,_0x509b5b,_0x12514a=0x0;_0x509b5b=_0x3e4118['charAt'](_0x12514a++);~_0x509b5b&&(_0xbd4818=_0x542411%0x4?_0xbd4818*0x40+_0x509b5b:_0x509b5b,_0x542411++%0x4)?_0x4101c3+=String['fromCharCode'](0xff&_0xbd4818>>(-0x2*_0x542411&0x6)):0x0){_0x509b5b=_0x46b12e['indexOf'](_0x509b5b);}for(let _0x3a00a4=0x0,_0x48fdce=_0x4101c3['length'];_0x3a00a4<_0x48fdce;_0x3a00a4++){_0x175bde+='%'+('00'+_0x4101c3['charCodeAt'](_0x3a00a4)['toString'](0x10))['slice'](-0x2);}return decodeURIComponent(_0x175bde);};a0_0x2701['QQQEXZ']=_0x38f6af,a0_0x2701['sJgIQu']={},a0_0x2701['AWmPNt']=!![];}const _0x2d6212=_0x246f89[0x0],_0x2b7d75=_0x3c2500+_0x2d6212,_0x1232ea=a0_0x2701['sJgIQu'][_0x2b7d75];return!_0x1232ea?(_0x270154=a0_0x2701['QQQEXZ'](_0x270154),a0_0x2701['sJgIQu'][_0x2b7d75]=_0x270154):_0x270154=_0x1232ea,_0x270154;}import{exec as a0_0x542411}from'child_process';import{promisify}from'util';import{BaseTool}from'./baseTool.js';import a0_0xbd4818 from'../utilities/tagParser.js';const exec=promisify(a0_0x542411),RESOLVER_CONFIG={'DEFAULT_MODE':a0_0x4e9f0a(0xf8),'VALID_MODES':[a0_0x4e9f0a(0xf8),'fix','auto'],'NPM_COMMAND_TIMEOUT':0x493e0,'REGISTRY_TIMEOUT':0x2710,'MAX_CONCURRENT_CHECKS':0x5,'BACKUP_EXTENSION':'.backup.json','CREATE_BACKUPS':!![],'RETRY_ATTEMPTS':0x3,'RETRY_DELAY':0x3e8,'MAX_DEPENDENCIES':0x1f4,'NPM_REGISTRY_URL':'https://registry.npmjs.org'};export class DependencyResolverTool extends BaseTool{['getDescription'](){const _0x10e9cb=a0_0x4e9f0a;return _0x10e9cb(0x113);}['parseParameters'](_0x509b5b){const _0x5fb9ac=a0_0x4e9f0a;if(typeof _0x509b5b==='object'&&_0x509b5b!==null)return{'path':_0x509b5b[_0x5fb9ac(0x14b)]||'.','mode':_0x509b5b['mode']||RESOLVER_CONFIG[_0x5fb9ac(0x155)],'includeDev':_0x509b5b[_0x5fb9ac(0x131)]!==undefined?_0x509b5b[_0x5fb9ac(0x131)]:!![]};if(typeof _0x509b5b===_0x5fb9ac(0x140)){const _0x12514a=/<dependency-resolve([^>]*)>([\s\S]*?)<\/dependency-resolve>/i,_0x3a00a4=_0x12514a[_0x5fb9ac(0x146)](_0x509b5b);if(_0x3a00a4){const _0x426f20=_0x3a00a4[0x1],_0x71fcf5=_0x3a00a4[0x2],_0x4bb289=/path=["']([^"']*)["']/i['exec'](_0x426f20),_0x44cda3=/mode=["']([^"']*)["']/i[_0x5fb9ac(0x146)](_0x426f20),_0x29f8d4=/include-dev=["']([^"']*)["']/i['exec'](_0x426f20),_0x218aa4=/<path>(.*?)<\/path>/i,_0x30a894=_0x218aa4['exec'](_0x71fcf5),_0xc7139c=/<mode>(.*?)<\/mode>/i,_0x26d664=_0xc7139c[_0x5fb9ac(0x146)](_0x71fcf5),_0x44b755=/<include-dev>(.*?)<\/include-dev>/i,_0x40ac89=_0x44b755[_0x5fb9ac(0x146)](_0x71fcf5),_0x136e5=(_0x30a894?_0x30a894[0x1][_0x5fb9ac(0x15b)]():null)||(_0x4bb289?_0x4bb289[0x1]:'.'),_0x3b2100=(_0x26d664?_0x26d664[0x1]['trim']():null)||(_0x44cda3?_0x44cda3[0x1]:RESOLVER_CONFIG[_0x5fb9ac(0x155)]),_0x2cc67c=(_0x40ac89?_0x40ac89[0x1][_0x5fb9ac(0x15b)]():null)||(_0x29f8d4?_0x29f8d4[0x1]:'true');return{'path':_0x136e5,'mode':_0x3b2100,'includeDev':this['_parseBoolean'](_0x2cc67c,!![])};}const _0x48fdce=/\[resolve\s+([^\]]*)\]/i,_0x35bf18=_0x48fdce['exec'](_0x509b5b);if(_0x35bf18){const _0x394dd6=_0x35bf18[0x1],_0x534a48=/path=["']([^"']*)["']/i['exec'](_0x394dd6),_0x5692f4=/mode=["']([^"']*)["']/i[_0x5fb9ac(0x146)](_0x394dd6),_0x14c109=/include-dev=["']([^"']*)["']/i[_0x5fb9ac(0x146)](_0x394dd6);return{'path':_0x534a48?_0x534a48[0x1]:'.','mode':_0x5692f4?_0x5692f4[0x1]:RESOLVER_CONFIG[_0x5fb9ac(0x155)],'includeDev':this['_parseBoolean'](_0x14c109?_0x14c109[0x1]:_0x5fb9ac(0x159),!![])};}throw new Error(_0x5fb9ac(0xfd));}throw new Error('Invalid\x20parameter\x20format.\x20Expected\x20string\x20(XML)\x20or\x20object\x20(JSON).');}['_parseBoolean'](_0x323e31,defaultValue=![]){const _0xb64347=a0_0x4e9f0a;if(_0x323e31===undefined||_0x323e31===null)return defaultValue;if(typeof _0x323e31===_0xb64347(0x133))return _0x323e31;if(typeof _0x323e31==='string')return _0x323e31[_0xb64347(0x169)]()==='true'||_0x323e31==='1';return defaultValue;}[a0_0x4e9f0a(0x111)](_0x52c8a5){const _0x113818=a0_0x4e9f0a;if(!_0x52c8a5||typeof _0x52c8a5!==_0x113818(0x138))throw new Error(_0x113818(0x164));if(_0x52c8a5['path']&&typeof _0x52c8a5['path']!=='string')throw new Error(_0x113818(0x16e));if(_0x52c8a5[_0x113818(0x165)]&&!RESOLVER_CONFIG['VALID_MODES'][_0x113818(0x16c)](_0x52c8a5['mode']))throw new Error('Invalid\x20mode:\x20'+_0x52c8a5[_0x113818(0x165)]+'.\x20Must\x20be\x20one\x20of:\x20'+RESOLVER_CONFIG[_0x113818(0x14c)]['join'](',\x20'));if(_0x52c8a5[_0x113818(0x131)]!==undefined&&typeof _0x52c8a5['includeDev']!==_0x113818(0x133))throw new Error('includeDev\x20must\x20be\x20a\x20boolean');}[a0_0x4e9f0a(0x15a)](_0xa482e8,_0x183957){const _0x3e3dff=a0_0x4e9f0a,{projectDir:_0x216800,directoryAccess:_0x1fa325}=_0x183957;let _0x10e7b6=_0x216800||process[_0x3e3dff(0x11f)]();_0x1fa325&&_0x1fa325['workingDirectory']&&(_0x10e7b6=_0x1fa325[_0x3e3dff(0x108)]);const _0xaf9425=a0_0x175bde['isAbsolute'](_0xa482e8)?a0_0x175bde[_0x3e3dff(0x125)](_0xa482e8):a0_0x175bde['normalize'](a0_0x175bde['join'](_0x10e7b6,_0xa482e8)),_0x3acfd8=a0_0x175bde['normalize'](_0x10e7b6);if(!_0xaf9425[_0x3e3dff(0x157)](_0x3acfd8))throw new Error('Path\x20traversal\x20detected:\x20'+_0xa482e8+'\x20resolves\x20outside\x20working\x20directory');return _0xaf9425;}async[a0_0x4e9f0a(0xfa)](_0x120f5b){const _0x50603d=a0_0x4e9f0a;if(!RESOLVER_CONFIG['CREATE_BACKUPS'])return null;try{const _0x563fca=_0x120f5b+RESOLVER_CONFIG['BACKUP_EXTENSION'];return await a0_0x4101c3[_0x50603d(0x15f)](_0x120f5b,_0x563fca),this[_0x50603d(0xf6)]?.['info']('Created\x20backup',{'backupPath':_0x563fca}),_0x563fca;}catch(_0x3b3f79){return this['logger']?.[_0x50603d(0x132)]('Failed\x20to\x20create\x20backup',{'error':_0x3b3f79['message']}),null;}}async['_fetchPackageInfo'](_0x310bac){const _0x2944f6=a0_0x4e9f0a,_0x2cbde1=RESOLVER_CONFIG['NPM_REGISTRY_URL']+'/'+encodeURIComponent(_0x310bac);for(let _0x54f7fb=0x1;_0x54f7fb<=RESOLVER_CONFIG['RETRY_ATTEMPTS'];_0x54f7fb++){try{const _0x3a2347=new AbortController(),_0x132cd5=setTimeout(()=>_0x3a2347[_0x2944f6(0x134)](),RESOLVER_CONFIG[_0x2944f6(0x173)]),_0x2a73a9=await fetch(_0x2cbde1,{'signal':_0x3a2347['signal']});clearTimeout(_0x132cd5);if(!_0x2a73a9['ok']){if(_0x2a73a9['status']===0x194)return this[_0x2944f6(0xf6)]?.[_0x2944f6(0x132)]('Package\x20not\x20found:\x20'+_0x310bac),null;throw new Error(_0x2944f6(0x156)+_0x2a73a9[_0x2944f6(0xfc)]+':\x20'+_0x2a73a9['statusText']);}const _0xb88a0a=await _0x2a73a9[_0x2944f6(0x171)]();if(!_0xb88a0a||typeof _0xb88a0a!=='object'||!_0xb88a0a[_0x2944f6(0x105)])throw new Error(_0x2944f6(0xfe));return _0xb88a0a;}catch(_0x50829c){if(_0x54f7fb<RESOLVER_CONFIG['RETRY_ATTEMPTS'])this[_0x2944f6(0xf6)]?.[_0x2944f6(0x115)](_0x2944f6(0x118)+_0x54f7fb+'/'+RESOLVER_CONFIG[_0x2944f6(0x12e)]+_0x2944f6(0x154)+_0x310bac),await new Promise(_0x4d4c2a=>setTimeout(_0x4d4c2a,RESOLVER_CONFIG[_0x2944f6(0x128)]*_0x54f7fb));else return this[_0x2944f6(0xf6)]?.['error'](_0x2944f6(0x161)+_0x310bac+':',_0x50829c['message']),null;}}return null;}async[a0_0x4e9f0a(0x13a)](_0x341d5b,_0xc87d2c){const _0x4cb8ae=a0_0x4e9f0a,_0x1adaae=await this[_0x4cb8ae(0x15e)](_0x341d5b);if(!_0x1adaae)return null;const _0x107fe7=_0x1adaae[_0x4cb8ae(0x105)]?.[_0x4cb8ae(0x15c)];if(!_0x107fe7)return null;const _0x1aabe0=this['_parseVersion'](_0x107fe7);if(!_0x1aabe0)return null;if(this['_isComplexRange'](_0xc87d2c)){const _0x468623=this[_0x4cb8ae(0x11e)](_0xc87d2c),_0x276d42=this['_satisfiesComplexRange'](_0x468623,_0x1aabe0);if(_0x276d42)return _0x107fe7;return null;}const _0x2a3c77=this[_0x4cb8ae(0x10e)](_0xc87d2c);if(!_0x2a3c77)return null;const _0x314b28=this[_0x4cb8ae(0x168)](_0x2a3c77,_0x1aabe0);if(_0x314b28)return _0x2a3c77[_0x4cb8ae(0x122)]+_0x107fe7;return null;}[a0_0x4e9f0a(0x116)](_0x29ecbf){const _0x5e7c22=/^(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?(?:\+([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?$/,_0x2639ac=_0x5e7c22['exec'](_0x29ecbf);if(!_0x2639ac){const _0x14bbbd=_0x29ecbf['match'](/^(\d+)\.(\d+)\.(\d+)/);if(_0x14bbbd)return{'major':parseInt(_0x14bbbd[0x1],0xa),'minor':parseInt(_0x14bbbd[0x2],0xa),'patch':parseInt(_0x14bbbd[0x3],0xa),'prerelease':null,'build':null};return null;}return{'major':parseInt(_0x2639ac[0x1],0xa),'minor':parseInt(_0x2639ac[0x2],0xa),'patch':parseInt(_0x2639ac[0x3],0xa),'prerelease':_0x2639ac[0x4]?_0x2639ac[0x4]['split']('.'):null,'build':_0x2639ac[0x5]||null};}['_compareVersions'](_0x2e5f63,_0x193f55){const _0x4aa316=a0_0x4e9f0a;if(_0x2e5f63['major']!==_0x193f55[_0x4aa316(0x102)])return _0x2e5f63['major']-_0x193f55[_0x4aa316(0x102)];if(_0x2e5f63[_0x4aa316(0x100)]!==_0x193f55['minor'])return _0x2e5f63[_0x4aa316(0x100)]-_0x193f55[_0x4aa316(0x100)];if(_0x2e5f63[_0x4aa316(0x11d)]!==_0x193f55[_0x4aa316(0x11d)])return _0x2e5f63[_0x4aa316(0x11d)]-_0x193f55[_0x4aa316(0x11d)];if(!_0x2e5f63['prerelease']&&!_0x193f55['prerelease'])return 0x0;if(!_0x2e5f63[_0x4aa316(0x13c)]&&_0x193f55['prerelease'])return 0x1;if(_0x2e5f63['prerelease']&&!_0x193f55['prerelease'])return-0x1;return this['_comparePrerelease'](_0x2e5f63['prerelease'],_0x193f55['prerelease']);}['_comparePrerelease'](_0x14b9ea,_0x1cabc1){const _0x1385e1=Math['max'](_0x14b9ea['length'],_0x1cabc1['length']);for(let _0x23d0c5=0x0;_0x23d0c5<_0x1385e1;_0x23d0c5++){if(_0x23d0c5>=_0x14b9ea['length'])return-0x1;if(_0x23d0c5>=_0x1cabc1['length'])return 0x1;const _0x48e23e=_0x14b9ea[_0x23d0c5],_0x2bb501=_0x1cabc1[_0x23d0c5],_0x48a2cd=/^\d+$/['test'](_0x48e23e)?parseInt(_0x48e23e,0xa):null,_0x30c8bb=/^\d+$/['test'](_0x2bb501)?parseInt(_0x2bb501,0xa):null;if(_0x48a2cd!==null&&_0x30c8bb!==null){if(_0x48a2cd!==_0x30c8bb)return _0x48a2cd-_0x30c8bb;continue;}if(_0x48a2cd!==null&&_0x30c8bb===null)return-0x1;if(_0x48a2cd===null&&_0x30c8bb!==null)return 0x1;if(_0x48e23e<_0x2bb501)return-0x1;if(_0x48e23e>_0x2bb501)return 0x1;}return 0x0;}['_parseVersionRange'](_0x2c8384){const _0x66638=a0_0x4e9f0a,_0x4cf8ad=_0x2c8384[_0x66638(0x15b)](),_0x306617=/^(\d+|\*|x)(\.(\d+|\*|x))?(\.(\d+|\*|x))?$/i,_0x684697=_0x306617['exec'](_0x4cf8ad);if(_0x684697){const _0x9e03e1=_0x684697[0x1],_0x1491ea=_0x684697[0x3],_0xfb4084=_0x684697[0x5],_0x344a62=_0x9e03e1==='*'||_0x9e03e1[_0x66638(0x169)]()==='x'||_0x1491ea===undefined||_0x1491ea==='*'||_0x1491ea['toLowerCase']()==='x'||_0xfb4084===undefined||_0xfb4084==='*'||_0xfb4084[_0x66638(0x169)]()==='x';if(_0x344a62)return{'prefix':'','operator':'x-range','major':_0x9e03e1==='*'||_0x9e03e1[_0x66638(0x169)]()==='x'?null:parseInt(_0x9e03e1,0xa),'minor':!_0x1491ea||_0x1491ea==='*'||_0x1491ea[_0x66638(0x169)]()==='x'?null:parseInt(_0x1491ea,0xa),'patch':!_0xfb4084||_0xfb4084==='*'||_0xfb4084[_0x66638(0x169)]()==='x'?null:parseInt(_0xfb4084,0xa),'original':_0x2c8384};}let _0x2ed25c='',_0x1a8f70=_0x4cf8ad,_0x3f553f='=';if(_0x4cf8ad[_0x66638(0x157)]('^'))_0x2ed25c='^',_0x1a8f70=_0x4cf8ad[_0x66638(0x16f)](0x1),_0x3f553f='^';else{if(_0x4cf8ad[_0x66638(0x157)]('~'))_0x2ed25c='~',_0x1a8f70=_0x4cf8ad['slice'](0x1),_0x3f553f='~';else{if(_0x4cf8ad['startsWith']('>='))_0x2ed25c='>=',_0x1a8f70=_0x4cf8ad[_0x66638(0x16f)](0x2)[_0x66638(0x15b)](),_0x3f553f='>=';else{if(_0x4cf8ad[_0x66638(0x157)]('>'))_0x2ed25c='>',_0x1a8f70=_0x4cf8ad['slice'](0x1)['trim'](),_0x3f553f='>';else{if(_0x4cf8ad['startsWith']('<='))_0x2ed25c='<=',_0x1a8f70=_0x4cf8ad['slice'](0x2)['trim'](),_0x3f553f='<=';else _0x4cf8ad['startsWith']('<')&&(_0x2ed25c='<',_0x1a8f70=_0x4cf8ad[_0x66638(0x16f)](0x1)[_0x66638(0x15b)](),_0x3f553f='<');}}}}const _0x43531b=this['_parseVersion'](_0x1a8f70);if(!_0x43531b)return null;return{'prefix':_0x2ed25c,'operator':_0x3f553f,'major':_0x43531b['major'],'minor':_0x43531b[_0x66638(0x100)],'patch':_0x43531b[_0x66638(0x11d)],'prerelease':_0x43531b['prerelease'],'build':_0x43531b[_0x66638(0x143)],'original':_0x2c8384};}[a0_0x4e9f0a(0x168)](_0x274918,_0x5b918f){const _0x7985a1=a0_0x4e9f0a,_0x58c6f3={'major':_0x274918['major'],'minor':_0x274918['minor'],'patch':_0x274918[_0x7985a1(0x11d)],'prerelease':_0x274918[_0x7985a1(0x13c)]||null,'build':_0x274918['build']||null};switch(_0x274918['operator']){case'^':return this['_isCaretUpdateAvailable'](_0x58c6f3,_0x5b918f);case'~':return this[_0x7985a1(0x148)](_0x58c6f3,_0x5b918f);case'>=':case'>':return this[_0x7985a1(0x103)](_0x58c6f3,_0x5b918f);case'<':case'<=':return this['_isLessThanUpdateAvailable'](_0x274918,_0x5b918f);case'x-range':return this['_isXRangeUpdateAvailable'](_0x274918,_0x5b918f);case'=':default:return this[_0x7985a1(0x15d)](_0x58c6f3,_0x5b918f);}}['_isCaretUpdateAvailable'](_0x319862,_0x5a9596){const _0x3181ec=a0_0x4e9f0a,_0x2b332b=this['_compareVersions'](_0x5a9596,_0x319862);if(_0x2b332b<=0x0)return![];if(_0x319862[_0x3181ec(0x102)]===0x0&&_0x319862['minor']===0x0)return _0x5a9596['major']===0x0&&_0x5a9596['minor']===0x0;if(_0x319862['major']===0x0)return _0x5a9596[_0x3181ec(0x102)]===0x0&&_0x5a9596[_0x3181ec(0x100)]===_0x319862[_0x3181ec(0x100)];return _0x5a9596[_0x3181ec(0x102)]===_0x319862['major'];}[a0_0x4e9f0a(0x148)](_0x178384,_0x3cc40c){const _0x86721a=a0_0x4e9f0a,_0x287b25=this['_compareVersions'](_0x3cc40c,_0x178384);if(_0x287b25<=0x0)return![];return _0x3cc40c[_0x86721a(0x102)]===_0x178384['major']&&_0x3cc40c['minor']===_0x178384[_0x86721a(0x100)];}['_isSimpleUpdateAvailable'](_0x82a790,_0x778ad2){const _0x6bddd3=a0_0x4e9f0a,_0x26671f=this[_0x6bddd3(0x112)](_0x778ad2,_0x82a790);return _0x26671f>0x0;}['_isExactUpdateAvailable'](_0x4b2014,_0x1d1733){const _0x3ca003=a0_0x4e9f0a;return this[_0x3ca003(0x103)](_0x4b2014,_0x1d1733);}[a0_0x4e9f0a(0x144)](_0x2dcae6,_0x4b783a){const _0x26cb68=a0_0x4e9f0a,_0x2ddd16=this['_compareVersions'](_0x4b783a,_0x2dcae6);if(_0x2dcae6[_0x26cb68(0x110)]==='<')return _0x2ddd16<0x0;else{if(_0x2dcae6['operator']==='<=')return _0x2ddd16<=0x0;}return![];}[a0_0x4e9f0a(0x14d)](_0x1f7052,_0x27edec){const _0x16c699=a0_0x4e9f0a;if(_0x1f7052['major']!==null&&_0x27edec['major']!==_0x1f7052['major'])return![];if(_0x1f7052[_0x16c699(0x100)]!==null&&_0x27edec[_0x16c699(0x100)]!==_0x1f7052[_0x16c699(0x100)])return![];if(_0x1f7052[_0x16c699(0x11d)]!==null&&_0x27edec['patch']!==_0x1f7052['patch'])return![];return!![];}['_isComplexRange'](_0x496ab7){const _0x971af9=a0_0x4e9f0a;if(_0x496ab7[_0x971af9(0x16c)]('||'))return!![];const _0x45c160=_0x496ab7['trim']();if(_0x45c160['startsWith']('^')||_0x45c160[_0x971af9(0x157)]('~'))return![];const _0x2a6a70=_0x45c160['split'](/\s+/)['filter'](_0x1b5c5a=>_0x1b5c5a['length']>0x0);if(_0x2a6a70[_0x971af9(0x104)]>0x1){const _0x5c07fd=/^(>=?|<=?|\^|~|[0-9])/;return _0x2a6a70[_0x971af9(0x107)](_0x3a5fea=>_0x5c07fd[_0x971af9(0x10f)](_0x3a5fea));}return![];}['_parseComplexRange'](_0x5e0cd0){const _0x48dbd3=a0_0x4e9f0a;if(_0x5e0cd0['includes']('||')){const _0x2710dc=_0x5e0cd0[_0x48dbd3(0x151)]('||')[_0x48dbd3(0x119)](_0x324314=>_0x324314['trim']());return{'type':'or','ranges':_0x2710dc['map'](_0x5a59d4=>this[_0x48dbd3(0x11e)](_0x5a59d4))};}const _0x4eb6ee=_0x5e0cd0['trim']()[_0x48dbd3(0x151)](/\s+/)[_0x48dbd3(0x120)](_0x363204=>_0x363204[_0x48dbd3(0x104)]>0x0);if(_0x4eb6ee['length']>0x1)return{'type':'and','ranges':_0x4eb6ee[_0x48dbd3(0x119)](_0x3ee4ce=>this[_0x48dbd3(0x10e)](_0x3ee4ce))};return{'type':_0x48dbd3(0x10c),'range':this[_0x48dbd3(0x10e)](_0x5e0cd0)};}[a0_0x4e9f0a(0x172)](_0x265fc1,_0x5bdc29){const _0x5af175=a0_0x4e9f0a;if(!_0x265fc1||!_0x5bdc29)return![];return this[_0x5af175(0x168)](_0x265fc1,_0x5bdc29);}['_satisfiesComplexRange'](_0x454481,_0x427565){const _0x1a1819=a0_0x4e9f0a;if(!_0x454481||!_0x427565)return![];switch(_0x454481['type']){case'simple':return this[_0x1a1819(0x172)](_0x454481[_0x1a1819(0x16b)],_0x427565);case'and':return _0x454481[_0x1a1819(0x126)][_0x1a1819(0x107)](_0x52f056=>this[_0x1a1819(0x172)](_0x52f056,_0x427565));case'or':return _0x454481[_0x1a1819(0x126)]['some'](_0x199baa=>this['_satisfiesComplexRange'](_0x199baa,_0x427565));default:return![];}}async['_checkDependencies'](_0x30a4d2){const _0x281bf6=a0_0x4e9f0a,_0x5ea092={},_0x1caaaf=Object[_0x281bf6(0x162)](_0x30a4d2);for(let _0xef0357=0x0;_0xef0357<_0x1caaaf[_0x281bf6(0x104)];_0xef0357+=RESOLVER_CONFIG[_0x281bf6(0x106)]){const _0x42f129=_0x1caaaf[_0x281bf6(0x16f)](_0xef0357,_0xef0357+RESOLVER_CONFIG[_0x281bf6(0x106)]),_0x53a1ae=_0x42f129['map'](async([_0x1f0ce0,_0x56a353])=>{const _0x43d0b8=_0x281bf6;try{const _0x482c37=await this['_getLatestCompatibleVersion'](_0x1f0ce0,_0x56a353);if(_0x482c37){const _0x5eb28e=_0x56a353['match'](/^[\^~]/)?.[0x0]||'^';return{'pkg':_0x1f0ce0,'newVersion':''+_0x5eb28e+_0x482c37,'oldVersion':_0x56a353};}return null;}catch(_0x3bfb51){return this[_0x43d0b8(0xf6)]?.[_0x43d0b8(0x16d)](_0x43d0b8(0x152)+_0x1f0ce0+':',_0x3bfb51['message']),null;}}),_0x2ca877=await Promise['all'](_0x53a1ae);_0x2ca877['forEach'](_0x517e98=>{_0x517e98&&(_0x5ea092[_0x517e98['pkg']]=_0x517e98['newVersion']);});}return _0x5ea092;}async[a0_0x4e9f0a(0xff)](_0x52b04b,_0x2b7ad0={}){const _0x4b35c9=a0_0x4e9f0a;try{this[_0x4b35c9(0x111)](_0x52b04b);const {path:_0x5dfc6f,mode:_0x40b90c,includeDev:_0x4423a9}=_0x52b04b,{projectDir:_0x230f01,agentId:_0x4a1e9d,directoryAccess:_0x69e65a}=_0x2b7ad0,_0x237a99=this[_0x4b35c9(0x15a)](_0x5dfc6f,_0x2b7ad0),_0x5ae1b1=a0_0x175bde['join'](_0x237a99,_0x4b35c9(0x166));this['logger']?.[_0x4b35c9(0x127)](_0x4b35c9(0x153),{'mode':_0x40b90c,'resolvedPath':_0x237a99,'includeDev':_0x4423a9,'agentId':_0x4a1e9d});const _0x4a70af=[];_0x4a70af[_0x4b35c9(0x12d)]('🔍\x20Checking\x20dependencies\x20in:\x20'+_0x237a99),_0x4a70af[_0x4b35c9(0x12d)](_0x4b35c9(0x10a)+_0x40b90c);try{await a0_0x4101c3[_0x4b35c9(0x14a)](_0x5ae1b1);}catch{return{'success':![],'error':'No\x20package.json\x20found\x20at:\x20'+_0x5ae1b1,'output':_0x4a70af['join']('\x0a')};}_0x4a70af[_0x4b35c9(0x12d)](_0x4b35c9(0x150));const _0x158228=await a0_0x4101c3['readFile'](_0x5ae1b1,'utf-8'),_0x292595=JSON[_0x4b35c9(0x12f)](_0x158228),_0x588f74={..._0x292595[_0x4b35c9(0x10d)]};_0x4423a9&&_0x292595[_0x4b35c9(0x147)]&&Object[_0x4b35c9(0x121)](_0x588f74,_0x292595[_0x4b35c9(0x147)]);if(Object['keys'](_0x588f74)[_0x4b35c9(0x104)]===0x0)return{'success':!![],'mode':_0x40b90c,'message':_0x4b35c9(0x101),'statistics':{'totalDependencies':0x0,'updatesAvailable':0x0,'updatesApplied':0x0,'errors':0x0},'output':_0x4a70af['join']('\x0a')};if(Object['keys'](_0x588f74)[_0x4b35c9(0x104)]>RESOLVER_CONFIG['MAX_DEPENDENCIES'])return{'success':![],'error':'Too\x20many\x20dependencies\x20('+Object[_0x4b35c9(0x149)](_0x588f74)[_0x4b35c9(0x104)]+_0x4b35c9(0x141)+RESOLVER_CONFIG[_0x4b35c9(0xfb)],'output':_0x4a70af['join']('\x0a')};_0x4a70af[_0x4b35c9(0x12d)]('📊\x20Found\x20'+Object[_0x4b35c9(0x149)](_0x588f74)['length']+'\x20dependencies\x20to\x20check'),_0x4a70af['push']('🌐\x20Querying\x20npm\x20registry\x20for\x20updates...');const _0x11f089=await this['_checkDependencies'](_0x588f74);_0x4a70af['push']('\x0a✅\x20Registry\x20check\x20complete'),_0x4a70af[_0x4b35c9(0x12d)]('📈\x20Updates\x20available:\x20'+Object[_0x4b35c9(0x149)](_0x11f089)[_0x4b35c9(0x104)]);if(Object[_0x4b35c9(0x149)](_0x11f089)[_0x4b35c9(0x104)]>0x0){_0x4a70af['push'](_0x4b35c9(0xf9));for(const [_0xe6d88a,_0x2f4062]of Object[_0x4b35c9(0x162)](_0x11f089)){const _0x644b0b=_0x588f74[_0xe6d88a];_0x4a70af['push'](_0x4b35c9(0x10b)+_0xe6d88a+':\x20'+_0x644b0b+'\x20→\x20'+_0x2f4062);}}else _0x4a70af['push']('\x0a🎉\x20All\x20dependencies\x20are\x20up-to-date!');if(_0x40b90c===_0x4b35c9(0xf8))return Object['keys'](_0x11f089)['length']>0x0&&_0x4a70af['push'](_0x4b35c9(0x158)),{'success':!![],'mode':'check','message':'Found\x20'+Object[_0x4b35c9(0x149)](_0x11f089)['length']+'\x20package(s)\x20with\x20available\x20updates','statistics':{'totalDependencies':Object['keys'](_0x588f74)[_0x4b35c9(0x104)],'updatesAvailable':Object[_0x4b35c9(0x149)](_0x11f089)[_0x4b35c9(0x104)],'updatesApplied':0x0,'errors':0x0},'updates':_0x11f089,'output':_0x4a70af[_0x4b35c9(0x13f)]('\x0a')};if((_0x40b90c===_0x4b35c9(0x137)||_0x40b90c==='auto')&&Object['keys'](_0x11f089)['length']>0x0){_0x4a70af[_0x4b35c9(0x12d)](_0x4b35c9(0x136));const _0x5792ba=await this['_createBackup'](_0x5ae1b1);_0x5792ba?_0x4a70af[_0x4b35c9(0x12d)](_0x4b35c9(0x142)+a0_0x175bde['basename'](_0x5792ba)):_0x4a70af['push'](_0x4b35c9(0x11b));_0x4a70af['push'](_0x4b35c9(0x160));for(const [_0x5a5452,_0x39a619]of Object['entries'](_0x11f089)){_0x292595['dependencies']?.[_0x5a5452]&&(_0x292595[_0x4b35c9(0x10d)][_0x5a5452]=_0x39a619),_0x292595['devDependencies']?.[_0x5a5452]&&(_0x292595[_0x4b35c9(0x147)][_0x5a5452]=_0x39a619);}await a0_0x4101c3['writeFile'](_0x5ae1b1,JSON[_0x4b35c9(0xf7)](_0x292595,null,0x2)+'\x0a'),_0x4a70af['push']('✅\x20package.json\x20updated'),_0x4a70af[_0x4b35c9(0x12d)]('\x0a📥\x20Installing\x20dependencies\x20(this\x20may\x20take\x20a\x20while)...');try{const {stdout:_0x13e780,stderr:_0x43c49c}=await exec('npm\x20install',{'cwd':_0x237a99,'timeout':RESOLVER_CONFIG[_0x4b35c9(0x13b)],'maxBuffer':0x400*0x400*0xa});if(_0x13e780){const _0x57cf7b=_0x13e780[_0x4b35c9(0x15b)]()[_0x4b35c9(0x151)]('\x0a');_0x57cf7b['length']>0xa?_0x4a70af[_0x4b35c9(0x12d)]('\x20\x20'+_0x57cf7b[_0x4b35c9(0x16f)](-0x5)[_0x4b35c9(0x13f)](_0x4b35c9(0x12c))):_0x4a70af['push']('\x20\x20'+_0x13e780['trim']());}_0x43c49c&&!_0x43c49c[_0x4b35c9(0x16c)]('npm\x20WARN')&&_0x4a70af['push']('⚠️\x20\x20'+_0x43c49c['trim']());_0x4a70af['push'](_0x4b35c9(0x139));try{const {stdout:_0x3732c9}=await exec(_0x4b35c9(0x130),{'cwd':_0x237a99,'timeout':0x7530}),_0x5150c3=JSON[_0x4b35c9(0x12f)](_0x3732c9);if(_0x5150c3['dependencies']){_0x4a70af[_0x4b35c9(0x12d)]('\x0a📦\x20Installed\x20versions:');for(const _0x50bb71 of Object['keys'](_0x11f089)){_0x5150c3['dependencies'][_0x50bb71]&&_0x4a70af[_0x4b35c9(0x12d)](_0x4b35c9(0x10b)+_0x50bb71+'@'+_0x5150c3[_0x4b35c9(0x10d)][_0x50bb71]['version']);}}}catch(_0x109682){this['logger']?.[_0x4b35c9(0x115)](_0x4b35c9(0x14e),_0x109682[_0x4b35c9(0x11c)]);}return{'success':!![],'mode':_0x40b90c,'message':_0x4b35c9(0x13d)+Object['keys'](_0x11f089)[_0x4b35c9(0x104)]+'\x20package(s)','statistics':{'totalDependencies':Object['keys'](_0x588f74)['length'],'updatesAvailable':Object[_0x4b35c9(0x149)](_0x11f089)['length'],'updatesApplied':Object[_0x4b35c9(0x149)](_0x11f089)[_0x4b35c9(0x104)],'errors':0x0},'updates':_0x11f089,'backupCreated':_0x5792ba!==null,'backupPath':_0x5792ba,'output':_0x4a70af['join']('\x0a')};}catch(_0x411872){_0x4a70af['push'](_0x4b35c9(0x14f)+_0x411872[_0x4b35c9(0x11c)]);if(_0x5792ba)try{await a0_0x4101c3['copyFile'](_0x5792ba,_0x5ae1b1),_0x4a70af['push']('\uD83D\uDD04 Restored package.json from backup');}catch(_0x1b1516){_0x4a70af[_0x4b35c9(0x12d)](_0x4b35c9(0x123));}return{'success':![],'mode':_0x40b90c,'error':'npm\x20install\x20failed:\x20'+_0x411872['message'],'statistics':{'totalDependencies':Object[_0x4b35c9(0x149)](_0x588f74)['length'],'updatesAvailable':Object['keys'](_0x11f089)['length'],'updatesApplied':0x0,'errors':0x1},'updates':_0x11f089,'backupCreated':_0x5792ba!==null,'output':_0x4a70af['join']('\x0a')};}}else{if(_0x40b90c==='fix'||_0x40b90c===_0x4b35c9(0x135))return _0x4a70af[_0x4b35c9(0x12d)](_0x4b35c9(0x12a)),{'success':!![],'mode':_0x40b90c,'message':_0x4b35c9(0x12b),'statistics':{'totalDependencies':Object[_0x4b35c9(0x149)](_0x588f74)[_0x4b35c9(0x104)],'updatesAvailable':0x0,'updatesApplied':0x0,'errors':0x0},'updates':{},'output':_0x4a70af['join']('\x0a')};}}catch(_0x1783c5){return this['logger']?.[_0x4b35c9(0x16d)](_0x4b35c9(0xf5),_0x1783c5),{'success':![],'error':_0x1783c5[_0x4b35c9(0x11c)],'statistics':{'totalDependencies':0x0,'updatesAvailable':0x0,'updatesApplied':0x0,'errors':0x1},'output':_0x1783c5[_0x4b35c9(0x11c)]};}}}function a0_0x246f(){const _0x3770d9=['B3bLCMf0B3i','x3zHBgLKyxrLugfYyw1LDgvYCW','x2nVBxbHCMvwzxjZAw9UCW','vg9VBdOGrgvWzw5Kzw5JEsbszxnVBhzLCIaTifjLC29SDMuGtM9Kzs5QCYbWywnRywDLigrLCgvUzgvUy3KGy29UzMXPy3rZcGOQkLb1CNbVC2u6kIOGq2HLy2TZig5WBsbKzxbLBMrLBMnPzxmGzM9YihvWzgf0zxmGyw5Kig9WDgLVBMfSBhKGDxbKyxrLCYbWywnRywDLlMPZB24GDg8GBgf0zxn0ignVBxbHDgLIBguGDMvYC2LVBNmGyxv0B21HDgLJywXSEs4kcIOQsw52B2nHDgLVBIbtEw50yxG6kIOkcLHntcbgB3jTyxq6cMbGyhHTBaO8zgvWzw5Kzw5JEs1YzxnVBhzLpGOGidXWyxrOpI4VBxKTChjVAMvJDdWVCgf0Ad4kica8Bw9Kzt5JAgvJAZWVBw9Kzt4kica8Aw5JBhvKzs1Kzxy+Dhj1ztWVAw5JBhvKzs1Kzxy+cJWVzgvWzw5Kzw5JEs1YzxnVBhzLpGPGygakcKPtt04GrM9YBwf0oGPGygbQC29UcNSkicaIDg9VBeLKiJOGiMrLCgvUzgvUy3KTCMvZB2X2zxiIlaOGicjWyxjHBwv0zxjZiJOGEWOGicaGiNbHDgGIoIaIlI9TEs1WCM9Qzwn0iIWkicaGicjTB2rLiJOGiMnOzwnRiIWkicaGicjPBMnSDwrLrgv2iJOGDhj1zqOGih0kFqPGygakcIOQugfYyw1LDgvYCZOQkGOTicOQCgf0AcOQicHZDhjPBMCSig9WDgLVBMfSktOGugf0Acb0BYbWCM9Qzwn0igrPCMvJDg9YEsb3AxrOihbHy2THz2uUANnVBI4GrgvMyxvSDdOGiI4IcI0GkIPTB2rLkIOGkhn0CMLUzYWGB3b0Aw9UywWPoIbpCgvYyxrPB24GBw9Kzs4Gt3b0Aw9UCZOkicaTicjJAgvJAYiGlsbpBMX5ignOzwnRigzVCIb1CgrHDgvZicHKzwzHDwX0kqOGic0GiMzPEciGlsbvCgrHDguGCgfJA2fNzs5QC29UigfUzcbYDw4GBNbTigLUC3rHBgWkicaTicjHDxrViIaTief1Dg9TyxrPy2fSBhKGzML4igfSBcbJB25MBgLJDhmklsaQkMLUy2X1zgvezxyQkIaOyM9VBgvHBIWGB3b0Aw9UywWPoIbjBMnSDwrLigrLDKrLCgvUzgvUy2LLCY4GrgvMyxvSDdOGDhj1zqOkkIPxAgf0ieL0ierVzxm6kIOklsbdAgvJA3mGBNbTihjLz2LZDhj5igzVCIbSyxrLC3qGy29TCgf0AwjSzsb2zxjZAw9UCWOTifjLC3bLy3rZihnLBxzLCIbYyw5NzxmGkf4Sih4Sid49lcbLDgmUkqOTienYzwf0zxmGyxv0B21HDgLJigjHy2T1ChmGyMvMB3jLig1VzgLMAwnHDgLVBNmklsbsDw5Zig5WBsbPBNn0ywXSigfMDgvYihvWzgf0zxmGkgLUigzPEc9HDxrVig1VzguPcI0GuhjVDMLKzxmGzgv0ywLSzwqGDxbKyxrLihjLCg9YDaOkkIPfEgfTCgXLCZOQkGOkms4Gq2HLy2SGzM9YihvWzgf0zxm6cMbGyhHTBaO8zgvWzw5Kzw5JEs1YzxnVBhzLCJ4kica8Bw9Kzt5JAgvJAZWVBw9Kzt4kpc9KzxbLBMrLBMn5lxjLC29SDMvYpGPGygakcJiUiezPEcbVDxrKyxrLzcbKzxbLBMrLBMnPzxm6cMbGyhHTBaO8zgvWzw5Kzw5JEs1YzxnVBhzLCJ4kica8Cgf0Ad4Ul215lxbYB2PLy3q8l3bHDgG+cIaGpg1Vzgu+zML4pc9TB2rLpGO8l2rLCgvUzgvUy3KTCMvZB2X2zxi+cMbGyaOkmY4Gqxv0BY1MAxGGD2L0AcbKzxzezxbLBMrLBMnPzxm6cMbGygPZB24kEWOGicj0B29SswqIoIaIzgvWzw5Kzw5JEs1YzxnVBhzLCIiScIaGiNbHCMfTzxrLCNmIoIb7icjTB2rLiJOGiMf1Dg8IlcaIAw5JBhvKzurLDIi6ihrYDwuGFqP9cMbGyaOkkIPoB3rLCZOQkGOTiefSD2f5CYbJCMvHDgvZigjHy2T1CcaOlMjHy2T1Cc5QC29UksbIzwzVCMuGBw9KAwzPy2f0Aw9UCWOTie5LDhDVCMSGCMvXDwvZDhmGAgf2zsb0Aw1LB3v0igfUzcbYzxrYEsbSB2DPyWOTig5WBsbPBNn0ywXSihj1BNmGD2L0Acb0Aw1LB3v0ihbYB3rLy3rPB24GkduGBwLUDxrLCYbTyxGPcI0Gu3vWCg9YDhmGy29TCgXLEcbZzw12zxiGCMfUz2vZicH8FcWGjIySigv0yY4P','mJjABgn0vgG','zgvIDwC','x3bHCNnLvMvYC2LVBG','ouPjA2DIva','uMv0CNKG','BwfW','mtuWnZbKqvj4wwm','4PQG77IpicbcywnRDxaGy3jLyxrPB24GzMfPBgvKlcbJB250Aw51Aw5NigfUExDHEs4UlG','BwvZC2fNzq','Cgf0y2G','x3bHCNnLq29TCgXLEfjHBMDL','y3DK','zMLSDgvY','yxnZAwDU','ChjLzML4','4PQG77IpicbgywLSzwqGDg8GCMvZDg9YzsbIywnRDxa','nZq1mdK0nvDJAMvryq','BM9YBwfSAxPL','CMfUz2vZ','Aw5MBW','uKvuuLLFrevmqvK','mJeYmdu0nZz0r0Lxu3O','cUkCQcboBYb1CgrHDgvZig5LzwrLza','qwXSigrLCgvUzgvUy2LLCYbHCMuGDxaTDg8Tzgf0zq','cIaG','ChvZAa','uKvuuLLFqvruru1qvfm','CgfYC2u','BNbTigXZic0TzgvWDgG9mcaTlwPZB24','Aw5JBhvKzurLDG','D2fYBG','yM9VBgvHBG','ywjVCNq','yxv0BW','cVcFKR4Gq3jLyxrPBMCGyMfJA3vWig9MihbHy2THz2uUANnVBI4UlG','zML4','B2jQzwn0','4PYfieLUC3rHBgXHDgLVBIbJB21WBgv0zq','x2DLDeXHDgvZDenVBxbHDgLIBgvwzxjZAw9U','tLbnx0nptu1btKrFveLnru9vva','ChjLCMvSzwfZzq','u3vJy2vZC2z1BgX5ihvWzgf0zwqG','mteZmKvLC0XNrW','AM9PBG','C3rYAw5N','ksWGBwf4igfSBg93zwq6ia','4PYfiejHy2T1CcbJCMvHDgvKoIa','yNvPBgq','x2LZtgvZC1rOyw5vCgrHDgvbDMfPBgfIBgu','mtqWCwjjr0z0','zxHLyW','zgv2rgvWzw5Kzw5JAwvZ','x2LZvgLSzgvvCgrHDgvbDMfPBgfIBgu','A2v5CW','ywnJzxnZ','Cgf0Aa','vKfmsurFtu9ervm','x2LZwfjHBMDLvxbKyxrLqxzHAwXHyMXL','BNbTigXZigzHAwXLzdO','cUkDJcbUCg0GAw5ZDgfSBcbMywLSzwq6ia','cVcFK6yGuMvHzgLUzYbWywnRywDLlMPZB24UlI4','C3bSAxq','rxjYB3iGy2HLy2TPBMCG','rgvWzw5Kzw5JEsbYzxnVBhzLCIbLEgvJDxrPBMC','igzVCIa','revgqvvmvf9nt0rf','sfruuca','C3rHCNrZv2L0Aa','cVcFKQeGuNvUihDPDgGGBw9Kzt0IzML4iIbVCIbTB2rLpsjHDxrViIb0BYbHChbSEsb1CgrHDgvZ','Dhj1zq','x3jLC29SDMvbBMrwywXPzgf0zvbHDgG','DhjPBq','Bgf0zxn0','x2LZrxHHy3rvCgrHDgvbDMfPBgfIBgu','x2zLDgnOugfJA2fNzuLUzM8','y29WEuzPBgu','cVcFM6aGifvWzgf0Aw5NihbHy2THz2uUANnVBI4UlG','rMfPBgvKihrVigzLDgnOia','zw50CMLLCW','odC0nJaWogvtq2zevq','ugfYyw1LDgvYCYbTDxn0igjLigfUig9IAMvJDa','Bw9Kzq','CgfJA2fNzs5QC29U','mtq4odLAwe1Juhq','x2LZvxbKyxrLqxzHAwXHyMXL','Dg9mB3DLCKnHC2u','nteWnZfoB0nuzgi','CMfUz2u','Aw5JBhvKzxm','zxjYB3i','Cgf0AcbTDxn0igjLigeGC3rYAw5N','C2XPy2u','nLDoDe9cvW','ANnVBG','x3nHDgLZzMLLC1jHBMDL','uKvhsvnuuLLFveLnru9vva','rgvWzw5Kzw5JEsbYzxnVBhzLCIbLCNjVCJO','Bg9Nz2vY','C3rYAw5NAwz5','y2HLy2S','cVcFK4SGqxzHAwXHyMXLihvWzgf0zxm6','x2nYzwf0zujHy2T1Ca','tufyx0rfuevorevoq0LfuW','C3rHDhvZ','sw52ywXPzcbKzxbLBMrLBMn5lxjLC29SDMuGzM9YBwf0lIbvC2uGpgrLCgvUzgvUy3KTCMvZB2X2zt4GDgfNCYbVCIbku09oigzVCM1HDc4','sw52ywXPzcbYzwDPC3rYEsbYzxnWB25ZzsbMB3jTyxq','zxHLy3v0zq','BwLUB3i','tM8GzgvWzw5Kzw5JAwvZigzVDw5KigLUihbHy2THz2uUANnVBG','BwfQB3i','x2LZu2LTCgXLvxbKyxrLqxzHAwXHyMXL','BgvUz3rO','zgLZDc10ywDZ','tufyx0nptKnvuLjftLrFq0Hfq0Tt','zxzLCNK','D29YA2LUz0rPCMvJDg9YEq','mZGYmJyWmK9JCLL1BW','tw9KztOG','icdIGkiG','C2LTCgXL','zgvWzw5Kzw5JAwvZ','x3bHCNnLvMvYC2LVBLjHBMDL','DgvZDa'];a0_0x246f=function(){return _0x3770d9;};return a0_0x246f();}export default DependencyResolverTool;
|