@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,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_0xbda7d4=a0_0x45fa;(function(_0x242d86,_0x14d1a1){const _0x307555=a0_0x45fa,_0x3d8c89=_0x242d86();while(!![]){try{const _0x526017=parseInt(_0x307555(0x11c))/0x1+parseInt(_0x307555(0xca))/0x2+parseInt(_0x307555(0xa9))/0x3*(parseInt(_0x307555(0xe4))/0x4)+parseInt(_0x307555(0x119))/0x5+parseInt(_0x307555(0x102))/0x6+-parseInt(_0x307555(0xe5))/0x7+-parseInt(_0x307555(0x111))/0x8;if(_0x526017===_0x14d1a1)break;else _0x3d8c89['push'](_0x3d8c89['shift']());}catch(_0x5925e5){_0x3d8c89['push'](_0x3d8c89['shift']());}}}(a0_0x15e1,0x7f976));import{promises as a0_0x4ffdd1}from'fs';function a0_0x15e1(){const _0x5d0850=['x2LZrxHHy3rvCgrHDgvbDMfPBgfIBgu','ChjLCMvSzwfZzq','Bg9Nz2vY','Cgf0Aa','Bwf4','tLbnx1jfr0Ltvfjzx1vsta','yw5K','zxHLyW','mtq5ntuZmM9bCLznta','cVcFK6yGsw5ZDgfSBgvKihzLCNnPB25ZoG','A2v5CW','sw52ywXPzcbYzwDPC3rYEsbYzxnWB25ZzsbMB3jTyxq','uKvuuLLFqvruru1qvfm','BwfW','cVcFK4SGqxzHAwXHyMXLihvWzgf0zxm6','Dg9mB3DLCKnHC2u','Ec1Yyw5Nzq','x2LZq2fYzxrvCgrHDgvbDMfPBgfIBgu','uKvuuLLFrevmqvK','AM9PBG','x3nHDgLZzMLLC1jHBMDL','ywjVCNq','tufyx0nptKnvuLjftLrFq0Hfq0Tt','B2jQzwn0','x3jLC29SDMvbBMrwywXPzgf0zvbHDgG','qKfds1vqx0vyvevou0LptG','Aw5JBhvKzxm','cUkCQcboBYb1CgrHDgvZig5LzwrLza','Aw5JBhvKzurLDG','C29Tzq','yxv0BW','BwvZC2fNzq','zxzLCNK','ugfYyw1LDgvYCYbTDxn0igjLigfUig9IAMvJDa','mJH1zMXnAKK','otGXmZm3sePswwfN','qwXSigrLCgvUzgvUy2LLCYbHCMuGDxaTDg8Tzgf0zq','ANnVBG','x2DLDeXHDgvZDenVBxbHDgLIBgvwzxjZAw9U','z2v0rgvZy3jPChrPB24','Aw5MBW','BNbTigLUC3rHBgW','zgv2rgvWzw5Kzw5JAwvZ','4PQG77Ipica','DgvZDa','yNvPBgq','cVcFK6uGsw5ZDgfSBgLUzYbKzxbLBMrLBMnPzxmGkhrOAxmGBwf5ihrHA2uGysb3AgLSzsKUlI4','uKvhsvnuuLLFveLnru9vva','D29YA2LUz0rPCMvJDg9YEq','Cgf0y2G','rMfPBgvKihrVignYzwf0zsbIywnRDxa','rgvWzw5Kzw5JEsbYzxnVBhzLCIbLCNjVCJO','x2LZvgLSzgvvCgrHDgvbDMfPBgfIBgu','8j+uJsbdAgvJA2LUzYbKzxbLBMrLBMnPzxmGAw46ia','ihjLC29SDMvZig91DhnPzguGD29YA2LUzYbKAxjLy3rVCNK','tM8GzgvWzw5Kzw5JAwvZigzVDw5KigLUihbHy2THz2uUANnVBG','C3rHCNrZv2L0Aa','C3bSAxq','ChvZAa','x2LZwfjHBMDLvxbKyxrLqxzHAwXHyMXL','q1jfqvrfx0jbq0Tvufm','x3bHCNnLvMvYC2LVBG','C3rHDhvZ','Bwf0y2G','mZuWmtK0ofDszK5uEa','x2LZtgvZC1rOyw5vCgrHDgvbDMfPBgfIBgu','zM9YrwfJAa','CgfYC2u','ywnJzxnZ','Bw9Kzq','cUkCHsbszwDPC3rYEsbJAgvJAYbJB21WBgv0zq','x3zHBgLKyxrLugfYyw1LDgvYCW','iokgKIa','zw50CMLLCW','D2fYBG','x2nOzwnRrgvWzw5Kzw5JAwvZ','Cgf0AcbTDxn0igjLigeGC3rYAw5N','8j+mKcbrDwvYEwLUzYbUCg0GCMvNAxn0CNKGzM9YihvWzgf0zxmUlI4','y3DK','mtC1nJK0ntzkt05xqNG','yM9VBgvHBG','x3bHCNnLq29TCgXLEfjHBMDL','AxnbyNnVBhv0zq','x3nHDgLZzMLLC0nVBxbSzxHsyw5Nzq','x3bHCNnLvMvYC2LVBLjHBMDL','x2LZvxbKyxrLqxzHAwXHyMXL','C3rYAw5NAwz5','mZe0mJKZmhzuzMXtuq','x3bHCNnLqM9VBgvHBG','C2XPy2u','ndG2mhrzsLzZAG','cVcFM6aGifvWzgf0Aw5NihbHy2THz2uUANnVBI4UlG','q3jLyxrLzcbIywnRDxa','C3rYAw5N','x2nVBxbHCMvwzxjZAw9UCW','BwLUB3i','ChjLzML4','B3bLCMf0B3i','DhLWzq','zgvIDwC','cUkDJcbUCg0GAw5ZDgfSBcbMywLSzwq6ia','yxnZAwDU','x2nVBxbHCMvqCMvYzwXLyxnL','Ahr0Chm6lY9YzwDPC3rYEs5UCg1QCY5VCMC','CMfUz2vZ','mZGZmtKZz3ntBLns','vg9VBdOGrgvWzw5Kzw5JEsbszxnVBhzLCIaTifjLC29SDMuGtM9Kzs5QCYbWywnRywDLigrLCgvUzgvUy3KGy29UzMXPy3rZcGOQkLb1CNbVC2u6kIOGq2HLy2TZig5WBsbKzxbLBMrLBMnPzxmGzM9YihvWzgf0zxmGyw5Kig9WDgLVBMfSBhKGDxbKyxrLCYbWywnRywDLlMPZB24GDg8GBgf0zxn0ignVBxbHDgLIBguGDMvYC2LVBNmGyxv0B21HDgLJywXSEs4kcIOQsw52B2nHDgLVBIbtEw50yxG6kIOkcLHntcbgB3jTyxq6cMbGyhHTBaO8zgvWzw5Kzw5JEs1YzxnVBhzLpGOGidXWyxrOpI4VBxKTChjVAMvJDdWVCgf0Ad4kica8Bw9Kzt5JAgvJAZWVBw9Kzt4kica8Aw5JBhvKzs1Kzxy+Dhj1ztWVAw5JBhvKzs1Kzxy+cJWVzgvWzw5Kzw5JEs1YzxnVBhzLpGPGygakcKPtt04GrM9YBwf0oGPGygbQC29UcNSkicaIDg9VBeLKiJOGiMrLCgvUzgvUy3KTCMvZB2X2zxiIlaOGicjWyxjHBwv0zxjZiJOGEWOGicaGiNbHDgGIoIaIlI9TEs1WCM9Qzwn0iIWkicaGicjTB2rLiJOGiMnOzwnRiIWkicaGicjPBMnSDwrLrgv2iJOGDhj1zqOGih0kFqPGygakcIOQugfYyw1LDgvYCZOQkGOTicOQCgf0AcOQicHZDhjPBMCSig9WDgLVBMfSktOGugf0Acb0BYbWCM9Qzwn0igrPCMvJDg9YEsb3AxrOihbHy2THz2uUANnVBI4GrgvMyxvSDdOGiI4IcI0GkIPTB2rLkIOGkhn0CMLUzYWGB3b0Aw9UywWPoIbpCgvYyxrPB24GBw9Kzs4Gt3b0Aw9UCZOkicaTicjJAgvJAYiGlsbpBMX5ignOzwnRigzVCIb1CgrHDgvZicHKzwzHDwX0kqOGic0GiMzPEciGlsbvCgrHDguGCgfJA2fNzs5QC29UigfUzcbYDw4GBNbTigLUC3rHBgWkicaTicjHDxrViIaTief1Dg9TyxrPy2fSBhKGzML4igfSBcbJB25MBgLJDhmklsaQkMLUy2X1zgvezxyQkIaOyM9VBgvHBIWGB3b0Aw9UywWPoIbjBMnSDwrLigrLDKrLCgvUzgvUy2LLCY4GrgvMyxvSDdOGDhj1zqOkkIPxAgf0ieL0ierVzxm6kIOklsbdAgvJA3mGBNbTihjLz2LZDhj5igzVCIbSyxrLC3qGy29TCgf0AwjSzsb2zxjZAw9UCWOTifjLC3bLy3rZihnLBxzLCIbYyw5NzxmGkf4Sih4Sid49lcbLDgmUkqOTienYzwf0zxmGyxv0B21HDgLJigjHy2T1ChmGyMvMB3jLig1VzgLMAwnHDgLVBNmklsbsDw5Zig5WBsbPBNn0ywXSigfMDgvYihvWzgf0zxmGkgLUigzPEc9HDxrVig1VzguPcI0GuhjVDMLKzxmGzgv0ywLSzwqGDxbKyxrLihjLCg9YDaOkkIPfEgfTCgXLCZOQkGOkms4Gq2HLy2SGzM9YihvWzgf0zxm6cMbGyhHTBaO8zgvWzw5Kzw5JEs1YzxnVBhzLCJ4kica8Bw9Kzt5JAgvJAZWVBw9Kzt4kpc9KzxbLBMrLBMn5lxjLC29SDMvYpGPGygakcJiUiezPEcbVDxrKyxrLzcbKzxbLBMrLBMnPzxm6cMbGyhHTBaO8zgvWzw5Kzw5JEs1YzxnVBhzLCJ4kica8Cgf0Ad4Ul215lxbYB2PLy3q8l3bHDgG+cIaGpg1Vzgu+zML4pc9TB2rLpGO8l2rLCgvUzgvUy3KTCMvZB2X2zxi+cMbGyaOkmY4Gqxv0BY1MAxGGD2L0AcbKzxzezxbLBMrLBMnPzxm6cMbGygPZB24kEWOGicj0B29SswqIoIaIzgvWzw5Kzw5JEs1YzxnVBhzLCIiScIaGiNbHCMfTzxrLCNmIoIb7icjTB2rLiJOGiMf1Dg8IlcaIAw5JBhvKzurLDIi6ihrYDwuGFqP9cMbGyaOkkIPoB3rLCZOQkGOTiefSD2f5CYbJCMvHDgvZigjHy2T1CcaOlMjHy2T1Cc5QC29UksbIzwzVCMuGBw9KAwzPy2f0Aw9UCWOTie5LDhDVCMSGCMvXDwvZDhmGAgf2zsb0Aw1LB3v0igfUzcbYzxrYEsbSB2DPyWOTig5WBsbPBNn0ywXSihj1BNmGD2L0Acb0Aw1LB3v0ihbYB3rLy3rPB24GkduGBwLUDxrLCYbTyxGPcI0Gu3vWCg9YDhmGy29TCgXLEcbZzw12zxiGCMfUz2vZicH8FcWGjIySigv0yY4P','C2LTCgXL','BNbTifDbuK4','4PYfihbHy2THz2uUANnVBIb1CgrHDgvK','BM9YBwfSAxPL','x2nYzwf0zujHy2T1Ca','zxjYB3i','4PYfieLUC3rHBgXHDgLVBIbJB21WBgv0zq','DhjPBq','zML4','Dhj1zq','x2LZu2LTCgXLvxbKyxrLqxzHAwXHyMXL','ywXS','zMLSDgvY','8j+tIIbgB3vUzca','x2zLDgnOugfJA2fNzuLUzM8','y2HLy2S','BgvUz3rO','BwfQB3i','cIaG','icdIGkiG','zgvWzw5Kzw5JAwvZ','vg9Vig1HBNKGzgvWzw5Kzw5JAwvZicG','ihbHy2THz2uOCYKGD2L0AcbHDMfPBgfIBguGDxbKyxrLCW'];a0_0x15e1=function(){return _0x5d0850;};return a0_0x15e1();}import a0_0xfd3da3 from'path';import{exec as a0_0x2c0f37}from'child_process';import{promisify}from'util';import{BaseTool}from'./baseTool.js';import a0_0x3a5cd5 from'../utilities/tagParser.js';const exec=promisify(a0_0x2c0f37),RESOLVER_CONFIG={'DEFAULT_MODE':a0_0xbda7d4(0xba),'VALID_MODES':['check',a0_0xbda7d4(0xb3),a0_0xbda7d4(0xe0)],'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':a0_0xbda7d4(0xa7)};function a0_0x45fa(_0x563825,_0x2a9702){_0x563825=_0x563825-0x9b;const _0x15e17d=a0_0x15e1();let _0x45fa44=_0x15e17d[_0x563825];if(a0_0x45fa['lkDqxd']===undefined){var _0x2cd63a=function(_0x2a8d44){const _0x162a42='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';let _0x4ffdd1='',_0xfd3da3='';for(let _0x2c0f37=0x0,_0x3a5cd5,_0x394093,_0x1db7f5=0x0;_0x394093=_0x2a8d44['charAt'](_0x1db7f5++);~_0x394093&&(_0x3a5cd5=_0x2c0f37%0x4?_0x3a5cd5*0x40+_0x394093:_0x394093,_0x2c0f37++%0x4)?_0x4ffdd1+=String['fromCharCode'](0xff&_0x3a5cd5>>(-0x2*_0x2c0f37&0x6)):0x0){_0x394093=_0x162a42['indexOf'](_0x394093);}for(let _0x28fad4=0x0,_0x5bf255=_0x4ffdd1['length'];_0x28fad4<_0x5bf255;_0x28fad4++){_0xfd3da3+='%'+('00'+_0x4ffdd1['charCodeAt'](_0x28fad4)['toString'](0x10))['slice'](-0x2);}return decodeURIComponent(_0xfd3da3);};a0_0x45fa['qdpUMP']=_0x2cd63a,a0_0x45fa['QRmwoo']={},a0_0x45fa['lkDqxd']=!![];}const _0x5c6735=_0x15e17d[0x0],_0x2c3d5e=_0x563825+_0x5c6735,_0x12dddb=a0_0x45fa['QRmwoo'][_0x2c3d5e];return!_0x12dddb?(_0x45fa44=a0_0x45fa['qdpUMP'](_0x45fa44),a0_0x45fa['QRmwoo'][_0x2c3d5e]=_0x45fa44):_0x45fa44=_0x12dddb,_0x45fa44;}export class DependencyResolverTool extends BaseTool{[a0_0xbda7d4(0xe9)](){const _0x2b26aa=a0_0xbda7d4;return _0x2b26aa(0xaa);}['parseParameters'](_0x394093){const _0x39adbe=a0_0xbda7d4;if(typeof _0x394093===_0x39adbe(0xd9)&&_0x394093!==null)return{'path':_0x394093[_0x39adbe(0xc5)]||'.','mode':_0x394093['mode']||RESOLVER_CONFIG['DEFAULT_MODE'],'includeDev':_0x394093['includeDev']!==undefined?_0x394093['includeDev']:!![]};if(typeof _0x394093===_0x39adbe(0x9d)){const _0x1db7f5=/<dependency-resolve([^>]*)>([\s\S]*?)<\/dependency-resolve>/i,_0x28fad4=_0x1db7f5[_0x39adbe(0xc9)](_0x394093);if(_0x28fad4){const _0x2e4a62=_0x28fad4[0x1],_0x3850e1=_0x28fad4[0x2],_0x1fd896=/path=["']([^"']*)["']/i['exec'](_0x2e4a62),_0x553153=/mode=["']([^"']*)["']/i['exec'](_0x2e4a62),_0x223688=/include-dev=["']([^"']*)["']/i[_0x39adbe(0xc9)](_0x2e4a62),_0x2b7723=/<path>(.*?)<\/path>/i,_0x870538=_0x2b7723[_0x39adbe(0xc9)](_0x3850e1),_0xbb7520=/<mode>(.*?)<\/mode>/i,_0xb32515=_0xbb7520[_0x39adbe(0xc9)](_0x3850e1),_0x162766=/<include-dev>(.*?)<\/include-dev>/i,_0x48adaf=_0x162766['exec'](_0x3850e1),_0x478e11=(_0x870538?_0x870538[0x1]['trim']():null)||(_0x1fd896?_0x1fd896[0x1]:'.'),_0x50b869=(_0xb32515?_0xb32515[0x1][_0x39adbe(0xb2)]():null)||(_0x553153?_0x553153[0x1]:RESOLVER_CONFIG['DEFAULT_MODE']),_0x380b22=(_0x48adaf?_0x48adaf[0x1]['trim']():null)||(_0x223688?_0x223688[0x1]:_0x39adbe(0xb4));return{'path':_0x478e11,'mode':_0x50b869,'includeDev':this[_0x39adbe(0x11a)](_0x380b22,!![])};}const _0x5bf255=/\[resolve\s+([^\]]*)\]/i,_0x3101f3=_0x5bf255['exec'](_0x394093);if(_0x3101f3){const _0x2360fd=_0x3101f3[0x1],_0x32d74c=/path=["']([^"']*)["']/i[_0x39adbe(0xc9)](_0x2360fd),_0x13b16e=/mode=["']([^"']*)["']/i['exec'](_0x2360fd),_0x4be62e=/include-dev=["']([^"']*)["']/i[_0x39adbe(0xc9)](_0x2360fd);return{'path':_0x32d74c?_0x32d74c[0x1]:'.','mode':_0x13b16e?_0x13b16e[0x1]:RESOLVER_CONFIG['DEFAULT_MODE'],'includeDev':this[_0x39adbe(0x11a)](_0x4be62e?_0x4be62e[0x1]:'true',!![])};}throw new Error('Invalid\x20dependency-resolve\x20format.\x20Use\x20<dependency-resolve>\x20tags\x20or\x20JSON\x20format.');}throw new Error('Invalid\x20parameter\x20format.\x20Expected\x20string\x20(XML)\x20or\x20object\x20(JSON).');}[a0_0xbda7d4(0x11a)](_0x28ac00,defaultValue=![]){const _0x14b3c1=a0_0xbda7d4;if(_0x28ac00===undefined||_0x28ac00===null)return defaultValue;if(typeof _0x28ac00==='boolean')return _0x28ac00;if(typeof _0x28ac00==='string')return _0x28ac00[_0x14b3c1(0xd1)]()==='true'||_0x28ac00==='1';return defaultValue;}[a0_0xbda7d4(0x109)](_0x2ef05d){const _0x3ecf31=a0_0xbda7d4;if(!_0x2ef05d||typeof _0x2ef05d!=='object')throw new Error(_0x3ecf31(0xe3));if(_0x2ef05d['path']&&typeof _0x2ef05d[_0x3ecf31(0xc5)]!=='string')throw new Error(_0x3ecf31(0x10e));if(_0x2ef05d[_0x3ecf31(0x107)]&&!RESOLVER_CONFIG['VALID_MODES']['includes'](_0x2ef05d[_0x3ecf31(0x107)]))throw new Error('Invalid\x20mode:\x20'+_0x2ef05d[_0x3ecf31(0x107)]+'.\x20Must\x20be\x20one\x20of:\x20'+RESOLVER_CONFIG['VALID_MODES'][_0x3ecf31(0xd5)](',\x20'));if(_0x2ef05d['includeDev']!==undefined&&typeof _0x2ef05d[_0x3ecf31(0xde)]!==_0x3ecf31(0x112))throw new Error('includeDev\x20must\x20be\x20a\x20boolean');}[a0_0xbda7d4(0xda)](_0xa4e578,_0x4d43d0){const _0x2ec016=a0_0xbda7d4,{projectDir:_0x5c9b91,directoryAccess:_0x2e59c6}=_0x4d43d0;let _0x5108df=_0x5c9b91||process[_0x2ec016(0x110)]();_0x2e59c6&&_0x2e59c6[_0x2ec016(0xf2)]&&(_0x5108df=_0x2e59c6[_0x2ec016(0xf2)]);const _0xcf0b52=a0_0xfd3da3[_0x2ec016(0x114)](_0xa4e578)?a0_0xfd3da3[_0x2ec016(0xae)](_0xa4e578):a0_0xfd3da3[_0x2ec016(0xae)](a0_0xfd3da3[_0x2ec016(0xd5)](_0x5108df,_0xa4e578)),_0x2fcf18=a0_0xfd3da3[_0x2ec016(0xae)](_0x5108df);if(!_0xcf0b52[_0x2ec016(0xfa)](_0x2fcf18))throw new Error('Path\x20traversal\x20detected:\x20'+_0xa4e578+_0x2ec016(0xf8));return _0xcf0b52;}async[a0_0xbda7d4(0xaf)](_0x50dc56){const _0x4a4543=a0_0xbda7d4;if(!RESOLVER_CONFIG[_0x4a4543(0xfe)])return null;try{const _0x3d31c5=_0x50dc56+RESOLVER_CONFIG[_0x4a4543(0xdb)];return await a0_0x4ffdd1['copyFile'](_0x50dc56,_0x3d31c5),this['logger']?.[_0x4a4543(0xea)](_0x4a4543(0x9c),{'backupPath':_0x3d31c5}),_0x3d31c5;}catch(_0x463ba0){return this['logger']?.[_0x4a4543(0x10c)](_0x4a4543(0xf4),{'error':_0x463ba0[_0x4a4543(0xe1)]}),null;}}async[a0_0xbda7d4(0xb9)](_0xc5392b){const _0x587139=a0_0xbda7d4,_0x30b855=RESOLVER_CONFIG[_0x587139(0xc7)]+'/'+encodeURIComponent(_0xc5392b);for(let _0x527a3a=0x1;_0x527a3a<=RESOLVER_CONFIG[_0x587139(0xce)];_0x527a3a++){try{const _0x3e4553=new AbortController(),_0x1a1716=setTimeout(()=>_0x3e4553[_0x587139(0xd7)](),RESOLVER_CONFIG[_0x587139(0xf1)]),_0x436c51=await fetch(_0x30b855,{'signal':_0x3e4553['signal']});clearTimeout(_0x1a1716);if(!_0x436c51['ok']){if(_0x436c51[_0x587139(0x100)]===0x194)return this[_0x587139(0xc4)]?.['warn']('Package\x20not\x20found:\x20'+_0xc5392b),null;throw new Error('HTTP\x20'+_0x436c51[_0x587139(0x100)]+':\x20'+_0x436c51['statusText']);}const _0x57643d=await _0x436c51[_0x587139(0xe7)]();if(!_0x57643d||typeof _0x57643d!=='object'||!_0x57643d['dist-tags'])throw new Error(_0x587139(0xcd));return _0x57643d;}catch(_0x224964){if(_0x527a3a<RESOLVER_CONFIG[_0x587139(0xce)])this['logger']?.['debug']('Retry\x20'+_0x527a3a+'/'+RESOLVER_CONFIG['RETRY_ATTEMPTS']+'\x20for\x20'+_0xc5392b),await new Promise(_0x159232=>setTimeout(_0x159232,RESOLVER_CONFIG[_0x587139(0xd4)]*_0x527a3a));else return this['logger']?.[_0x587139(0xb0)]('Failed\x20to\x20fetch\x20'+_0xc5392b+':',_0x224964[_0x587139(0xe1)]),null;}}return null;}async[a0_0xbda7d4(0xe8)](_0x20585c,_0x150547){const _0xda3349=a0_0xbda7d4,_0xc39aa5=await this['_fetchPackageInfo'](_0x20585c);if(!_0xc39aa5)return null;const _0x2d00f0=_0xc39aa5['dist-tags']?.['latest'];if(!_0x2d00f0)return null;const _0x1cce93=this[_0xda3349(0xff)](_0x2d00f0);if(!_0x1cce93)return null;if(this['_isComplexRange'](_0x150547)){const _0x306ec2=this[_0xda3349(0x113)](_0x150547),_0x1a89fd=this[_0xda3349(0x115)](_0x306ec2,_0x1cce93);if(_0x1a89fd)return _0x2d00f0;return null;}const _0x44e592=this[_0xda3349(0x116)](_0x150547);if(!_0x44e592)return null;const _0x5246c0=this[_0xda3349(0x117)](_0x44e592,_0x1cce93);if(_0x5246c0)return _0x44e592[_0xda3349(0xa0)]+_0x2d00f0;return null;}[a0_0xbda7d4(0xff)](_0x3fd607){const _0x1a4d87=a0_0xbda7d4,_0x136063=/^(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?(?:\+([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?$/,_0x1185ab=_0x136063[_0x1a4d87(0xc9)](_0x3fd607);if(!_0x1185ab){const _0x14a53a=_0x3fd607[_0x1a4d87(0x101)](/^(\d+)\.(\d+)\.(\d+)/);if(_0x14a53a)return{'major':parseInt(_0x14a53a[0x1],0xa),'minor':parseInt(_0x14a53a[0x2],0xa),'patch':parseInt(_0x14a53a[0x3],0xa),'prerelease':null,'build':null};return null;}return{'major':parseInt(_0x1185ab[0x1],0xa),'minor':parseInt(_0x1185ab[0x2],0xa),'patch':parseInt(_0x1185ab[0x3],0xa),'prerelease':_0x1185ab[0x4]?_0x1185ab[0x4]['split']('.'):null,'build':_0x1185ab[0x5]||null};}[a0_0xbda7d4(0x9e)](_0x18ba79,_0x5c4853){const _0x53f816=a0_0xbda7d4;if(_0x18ba79[_0x53f816(0xbc)]!==_0x5c4853[_0x53f816(0xbc)])return _0x18ba79['major']-_0x5c4853[_0x53f816(0xbc)];if(_0x18ba79['minor']!==_0x5c4853[_0x53f816(0x9f)])return _0x18ba79[_0x53f816(0x9f)]-_0x5c4853['minor'];if(_0x18ba79['patch']!==_0x5c4853['patch'])return _0x18ba79['patch']-_0x5c4853[_0x53f816(0xf3)];if(!_0x18ba79['prerelease']&&!_0x5c4853['prerelease'])return 0x0;if(!_0x18ba79[_0x53f816(0xc3)]&&_0x5c4853[_0x53f816(0xc3)])return 0x1;if(_0x18ba79[_0x53f816(0xc3)]&&!_0x5c4853['prerelease'])return-0x1;return this[_0x53f816(0xa6)](_0x18ba79[_0x53f816(0xc3)],_0x5c4853['prerelease']);}['_comparePrerelease'](_0x4ad632,_0x556fb3){const _0x55fd3c=a0_0xbda7d4,_0x1c0f4b=Math[_0x55fd3c(0xc6)](_0x4ad632[_0x55fd3c(0xbb)],_0x556fb3[_0x55fd3c(0xbb)]);for(let _0xba6979=0x0;_0xba6979<_0x1c0f4b;_0xba6979++){if(_0xba6979>=_0x4ad632['length'])return-0x1;if(_0xba6979>=_0x556fb3[_0x55fd3c(0xbb)])return 0x1;const _0x14455d=_0x4ad632[_0xba6979],_0x2ae625=_0x556fb3[_0xba6979],_0x2f567a=/^\d+$/['test'](_0x14455d)?parseInt(_0x14455d,0xa):null,_0x1af856=/^\d+$/[_0x55fd3c(0xee)](_0x2ae625)?parseInt(_0x2ae625,0xa):null;if(_0x2f567a!==null&&_0x1af856!==null){if(_0x2f567a!==_0x1af856)return _0x2f567a-_0x1af856;continue;}if(_0x2f567a!==null&&_0x1af856===null)return-0x1;if(_0x2f567a===null&&_0x1af856!==null)return 0x1;if(_0x14455d<_0x2ae625)return-0x1;if(_0x14455d>_0x2ae625)return 0x1;}return 0x0;}[a0_0xbda7d4(0x116)](_0xbe834b){const _0x3c6bc2=a0_0xbda7d4,_0x4fe834=_0xbe834b[_0x3c6bc2(0xb2)](),_0x250f2c=/^(\d+|\*|x)(\.(\d+|\*|x))?(\.(\d+|\*|x))?$/i,_0x5d1d09=_0x250f2c['exec'](_0x4fe834);if(_0x5d1d09){const _0x482db6=_0x5d1d09[0x1],_0xcd574b=_0x5d1d09[0x3],_0x5ed672=_0x5d1d09[0x5],_0xecbe17=_0x482db6==='*'||_0x482db6[_0x3c6bc2(0xd1)]()==='x'||_0xcd574b===undefined||_0xcd574b==='*'||_0xcd574b['toLowerCase']()==='x'||_0x5ed672===undefined||_0x5ed672==='*'||_0x5ed672['toLowerCase']()==='x';if(_0xecbe17)return{'prefix':'','operator':_0x3c6bc2(0xd2),'major':_0x482db6==='*'||_0x482db6['toLowerCase']()==='x'?null:parseInt(_0x482db6,0xa),'minor':!_0xcd574b||_0xcd574b==='*'||_0xcd574b[_0x3c6bc2(0xd1)]()==='x'?null:parseInt(_0xcd574b,0xa),'patch':!_0x5ed672||_0x5ed672==='*'||_0x5ed672['toLowerCase']()==='x'?null:parseInt(_0x5ed672,0xa),'original':_0xbe834b};}let _0x496dd2='',_0x5702f3=_0x4fe834,_0x5235c1='=';if(_0x4fe834['startsWith']('^'))_0x496dd2='^',_0x5702f3=_0x4fe834['slice'](0x1),_0x5235c1='^';else{if(_0x4fe834['startsWith']('~'))_0x496dd2='~',_0x5702f3=_0x4fe834[_0x3c6bc2(0x11b)](0x1),_0x5235c1='~';else{if(_0x4fe834[_0x3c6bc2(0xfa)]('>='))_0x496dd2='>=',_0x5702f3=_0x4fe834[_0x3c6bc2(0x11b)](0x2)[_0x3c6bc2(0xb2)](),_0x5235c1='>=';else{if(_0x4fe834[_0x3c6bc2(0xfa)]('>'))_0x496dd2='>',_0x5702f3=_0x4fe834[_0x3c6bc2(0x11b)](0x1)['trim'](),_0x5235c1='>';else{if(_0x4fe834['startsWith']('<='))_0x496dd2='<=',_0x5702f3=_0x4fe834['slice'](0x2)['trim'](),_0x5235c1='<=';else _0x4fe834[_0x3c6bc2(0xfa)]('<')&&(_0x496dd2='<',_0x5702f3=_0x4fe834['slice'](0x1)[_0x3c6bc2(0xb2)](),_0x5235c1='<');}}}}const _0x54489c=this['_parseVersion'](_0x5702f3);if(!_0x54489c)return null;return{'prefix':_0x496dd2,'operator':_0x5235c1,'major':_0x54489c[_0x3c6bc2(0xbc)],'minor':_0x54489c[_0x3c6bc2(0x9f)],'patch':_0x54489c['patch'],'prerelease':_0x54489c[_0x3c6bc2(0xc3)],'build':_0x54489c['build'],'original':_0xbe834b};}[a0_0xbda7d4(0x117)](_0x32f4b1,_0x3ef78d){const _0x3ed852=a0_0xbda7d4,_0x216809={'major':_0x32f4b1['major'],'minor':_0x32f4b1[_0x3ed852(0x9f)],'patch':_0x32f4b1[_0x3ed852(0xf3)],'prerelease':_0x32f4b1[_0x3ed852(0xc3)]||null,'build':_0x32f4b1[_0x3ed852(0xef)]||null};switch(_0x32f4b1[_0x3ed852(0xa1)]){case'^':return this[_0x3ed852(0xd3)](_0x216809,_0x3ef78d);case'~':return this['_isTildeUpdateAvailable'](_0x216809,_0x3ef78d);case'>=':case'>':return this['_isSimpleUpdateAvailable'](_0x216809,_0x3ef78d);case'<':case'<=':return this[_0x3ed852(0x103)](_0x32f4b1,_0x3ef78d);case'x-range':return this[_0x3ed852(0xfd)](_0x32f4b1,_0x3ef78d);case'=':default:return this['_isExactUpdateAvailable'](_0x216809,_0x3ef78d);}}['_isCaretUpdateAvailable'](_0xf8c7d5,_0x42a554){const _0x591707=a0_0xbda7d4,_0x559ff3=this['_compareVersions'](_0x42a554,_0xf8c7d5);if(_0x559ff3<=0x0)return![];if(_0xf8c7d5[_0x591707(0xbc)]===0x0&&_0xf8c7d5[_0x591707(0x9f)]===0x0)return _0x42a554[_0x591707(0xbc)]===0x0&&_0x42a554['minor']===0x0;if(_0xf8c7d5['major']===0x0)return _0x42a554[_0x591707(0xbc)]===0x0&&_0x42a554['minor']===_0xf8c7d5[_0x591707(0x9f)];return _0x42a554['major']===_0xf8c7d5[_0x591707(0xbc)];}[a0_0xbda7d4(0xf6)](_0x32fc69,_0x4de5dc){const _0x49db25=a0_0xbda7d4,_0x4cb0bc=this[_0x49db25(0x9e)](_0x4de5dc,_0x32fc69);if(_0x4cb0bc<=0x0)return![];return _0x4de5dc['major']===_0x32fc69['major']&&_0x4de5dc[_0x49db25(0x9f)]===_0x32fc69[_0x49db25(0x9f)];}[a0_0xbda7d4(0xb5)](_0x5c8e23,_0x535e73){const _0x267378=this['_compareVersions'](_0x535e73,_0x5c8e23);return _0x267378>0x0;}[a0_0xbda7d4(0xc2)](_0x48cbca,_0x1ab732){const _0x2f3b68=a0_0xbda7d4;return this[_0x2f3b68(0xb5)](_0x48cbca,_0x1ab732);}[a0_0xbda7d4(0x103)](_0x256c0e,_0x4c81fd){const _0x39eb9e=a0_0xbda7d4,_0x3b9fc8=this[_0x39eb9e(0x9e)](_0x4c81fd,_0x256c0e);if(_0x256c0e['operator']==='<')return _0x3b9fc8<0x0;else{if(_0x256c0e['operator']==='<=')return _0x3b9fc8<=0x0;}return![];}[a0_0xbda7d4(0xfd)](_0xfc694b,_0x954a9c){const _0x5ca211=a0_0xbda7d4;if(_0xfc694b[_0x5ca211(0xbc)]!==null&&_0x954a9c[_0x5ca211(0xbc)]!==_0xfc694b[_0x5ca211(0xbc)])return![];if(_0xfc694b['minor']!==null&&_0x954a9c[_0x5ca211(0x9f)]!==_0xfc694b['minor'])return![];if(_0xfc694b[_0x5ca211(0xf3)]!==null&&_0x954a9c['patch']!==_0xfc694b['patch'])return![];return!![];}['_isComplexRange'](_0x3239e1){const _0x427b0d=a0_0xbda7d4;if(_0x3239e1[_0x427b0d(0xdc)]('||'))return!![];const _0x542b2a=_0x3239e1['trim']();if(_0x542b2a[_0x427b0d(0xfa)]('^')||_0x542b2a['startsWith']('~'))return![];const _0x31641f=_0x542b2a[_0x427b0d(0xfb)](/\s+/)[_0x427b0d(0xb7)](_0x2c1e40=>_0x2c1e40['length']>0x0);if(_0x31641f[_0x427b0d(0xbb)]>0x1){const _0x163c4a=/^(>=?|<=?|\^|~|[0-9])/;return _0x31641f['every'](_0x208ae1=>_0x163c4a['test'](_0x208ae1));}return![];}[a0_0xbda7d4(0x113)](_0x10da05){const _0x45c01b=a0_0xbda7d4;if(_0x10da05['includes']('||')){const _0x31a872=_0x10da05[_0x45c01b(0xfb)]('||')[_0x45c01b(0xcf)](_0xc66558=>_0xc66558['trim']());return{'type':'or','ranges':_0x31a872['map'](_0x3522d4=>this[_0x45c01b(0x113)](_0x3522d4))};}const _0x126f22=_0x10da05[_0x45c01b(0xb2)]()['split'](/\s+/)[_0x45c01b(0xb7)](_0x5ebd2c=>_0x5ebd2c[_0x45c01b(0xbb)]>0x0);if(_0x126f22[_0x45c01b(0xbb)]>0x1)return{'type':_0x45c01b(0xc8),'ranges':_0x126f22[_0x45c01b(0xcf)](_0x2d435f=>this['_parseVersionRange'](_0x2d435f))};return{'type':'simple','range':this['_parseVersionRange'](_0x10da05)};}['_satisfiesRange'](_0x122b54,_0x1dda86){if(!_0x122b54||!_0x1dda86)return![];return this['_isUpdateAvailable'](_0x122b54,_0x1dda86);}['_satisfiesComplexRange'](_0x2cc755,_0x55e296){const _0x12b80b=a0_0xbda7d4;if(!_0x2cc755||!_0x55e296)return![];switch(_0x2cc755[_0x12b80b(0xa2)]){case _0x12b80b(0xab):return this[_0x12b80b(0xd6)](_0x2cc755['range'],_0x55e296);case _0x12b80b(0xc8):return _0x2cc755['ranges'][_0x12b80b(0xe2)](_0x536172=>this['_satisfiesRange'](_0x536172,_0x55e296));case'or':return _0x2cc755[_0x12b80b(0xa8)][_0x12b80b(0xdf)](_0x34e0e9=>this[_0x12b80b(0x115)](_0x34e0e9,_0x55e296));default:return![];}}async[a0_0xbda7d4(0x10d)](_0x17b15f){const _0x4da515=a0_0xbda7d4,_0x122dcc={},_0x449754=Object['entries'](_0x17b15f);for(let _0x3c4620=0x0;_0x3c4620<_0x449754[_0x4da515(0xbb)];_0x3c4620+=RESOLVER_CONFIG['MAX_CONCURRENT_CHECKS']){const _0x3b2836=_0x449754[_0x4da515(0x11b)](_0x3c4620,_0x3c4620+RESOLVER_CONFIG[_0x4da515(0xd8)]),_0x176293=_0x3b2836['map'](async([_0x2067d5,_0x392929])=>{const _0x5948ed=_0x4da515;try{const _0x2f5ee6=await this[_0x5948ed(0xe8)](_0x2067d5,_0x392929);if(_0x2f5ee6){const _0x52fda5=_0x392929[_0x5948ed(0x101)](/^[\^~]/)?.[0x0]||'^';return{'pkg':_0x2067d5,'newVersion':''+_0x52fda5+_0x2f5ee6,'oldVersion':_0x392929};}return null;}catch(_0x64c9cc){return this['logger']?.['error']('Error\x20checking\x20'+_0x2067d5+':',_0x64c9cc['message']),null;}}),_0x2893d6=await Promise[_0x4da515(0xb6)](_0x176293);_0x2893d6[_0x4da515(0x104)](_0x29b20e=>{_0x29b20e&&(_0x122dcc[_0x29b20e['pkg']]=_0x29b20e['newVersion']);});}return _0x122dcc;}async['execute'](_0x3c2fb0,_0x45bdcf={}){const _0x5c2fae=a0_0xbda7d4;try{this[_0x5c2fae(0x109)](_0x3c2fb0);const {path:_0x4047b8,mode:_0x47ba1a,includeDev:_0x51a4d3}=_0x3c2fb0,{projectDir:_0x49e4b6,agentId:_0x12237a,directoryAccess:_0x1908ad}=_0x45bdcf,_0x49c42d=this[_0x5c2fae(0xda)](_0x4047b8,_0x45bdcf),_0x243434=a0_0xfd3da3['join'](_0x49c42d,'package.json');this['logger']?.[_0x5c2fae(0xea)]('Dependency\x20resolver\x20executing',{'mode':_0x47ba1a,'resolvedPath':_0x49c42d,'includeDev':_0x51a4d3,'agentId':_0x12237a});const _0x4872b8=[];_0x4872b8['push'](_0x5c2fae(0xf7)+_0x49c42d),_0x4872b8[_0x5c2fae(0xfc)]('Mode:\x20'+_0x47ba1a);try{await a0_0x4ffdd1[_0x5c2fae(0x106)](_0x243434);}catch{return{'success':![],'error':'No\x20package.json\x20found\x20at:\x20'+_0x243434,'output':_0x4872b8[_0x5c2fae(0xd5)]('\x0a')};}_0x4872b8['push']('\x0a📦\x20Reading\x20package.json...');const _0x27a66e=await a0_0x4ffdd1['readFile'](_0x243434,'utf-8'),_0x43d6cc=JSON['parse'](_0x27a66e),_0x3f97db={..._0x43d6cc[_0x5c2fae(0xbf)]};_0x51a4d3&&_0x43d6cc['devDependencies']&&Object[_0x5c2fae(0xa5)](_0x3f97db,_0x43d6cc['devDependencies']);if(Object['keys'](_0x3f97db)['length']===0x0)return{'success':!![],'mode':_0x47ba1a,'message':_0x5c2fae(0xf9),'statistics':{'totalDependencies':0x0,'updatesAvailable':0x0,'updatesApplied':0x0,'errors':0x0},'output':_0x4872b8[_0x5c2fae(0xd5)]('\x0a')};if(Object[_0x5c2fae(0xcc)](_0x3f97db)['length']>RESOLVER_CONFIG['MAX_DEPENDENCIES'])return{'success':![],'error':_0x5c2fae(0xc0)+Object[_0x5c2fae(0xcc)](_0x3f97db)[_0x5c2fae(0xbb)]+'),\x20max\x20allowed:\x20'+RESOLVER_CONFIG['MAX_DEPENDENCIES'],'output':_0x4872b8[_0x5c2fae(0xd5)]('\x0a')};_0x4872b8[_0x5c2fae(0xfc)](_0x5c2fae(0xb8)+Object['keys'](_0x3f97db)[_0x5c2fae(0xbb)]+'\x20dependencies\x20to\x20check'),_0x4872b8[_0x5c2fae(0xfc)](_0x5c2fae(0x10f));const _0x479918=await this[_0x5c2fae(0x10d)](_0x3f97db);_0x4872b8['push'](_0x5c2fae(0x108)),_0x4872b8[_0x5c2fae(0xfc)]('📈\x20Updates\x20available:\x20'+Object[_0x5c2fae(0xcc)](_0x479918)[_0x5c2fae(0xbb)]);if(Object[_0x5c2fae(0xcc)](_0x479918)['length']>0x0){_0x4872b8[_0x5c2fae(0xfc)](_0x5c2fae(0xd0));for(const [_0x56dbe2,_0x10ee3e]of Object[_0x5c2fae(0x10b)](_0x479918)){const _0x8da24b=_0x3f97db[_0x56dbe2];_0x4872b8['push']('\x20\x20•\x20'+_0x56dbe2+':\x20'+_0x8da24b+_0x5c2fae(0x10a)+_0x10ee3e);}}else _0x4872b8['push']('\x0a🎉\x20All\x20dependencies\x20are\x20up-to-date!');if(_0x47ba1a===_0x5c2fae(0xba))return Object[_0x5c2fae(0xcc)](_0x479918)['length']>0x0&&_0x4872b8[_0x5c2fae(0xfc)]('\x0a💡\x20Run\x20with\x20mode=\x22fix\x22\x20or\x20mode=\x22auto\x22\x20to\x20apply\x20updates'),{'success':!![],'mode':_0x5c2fae(0xba),'message':'Found\x20'+Object['keys'](_0x479918)[_0x5c2fae(0xbb)]+_0x5c2fae(0xc1),'statistics':{'totalDependencies':Object[_0x5c2fae(0xcc)](_0x3f97db)[_0x5c2fae(0xbb)],'updatesAvailable':Object[_0x5c2fae(0xcc)](_0x479918)[_0x5c2fae(0xbb)],'updatesApplied':0x0,'errors':0x0},'updates':_0x479918,'output':_0x4872b8['join']('\x0a')};if((_0x47ba1a===_0x5c2fae(0xb3)||_0x47ba1a==='auto')&&Object['keys'](_0x479918)[_0x5c2fae(0xbb)]>0x0){_0x4872b8['push']('\x0a💾\x20Creating\x20backup\x20of\x20package.json...');const _0x346708=await this[_0x5c2fae(0xaf)](_0x243434);_0x346708?_0x4872b8['push']('✅\x20Backup\x20created:\x20'+a0_0xfd3da3['basename'](_0x346708)):_0x4872b8['push']('⚠️\x20\x20Backup\x20creation\x20failed,\x20continuing\x20anyway...');_0x4872b8[_0x5c2fae(0xfc)](_0x5c2fae(0x9b));for(const [_0x45a59d,_0x540d17]of Object[_0x5c2fae(0x10b)](_0x479918)){_0x43d6cc['dependencies']?.[_0x45a59d]&&(_0x43d6cc[_0x5c2fae(0xbf)][_0x45a59d]=_0x540d17),_0x43d6cc[_0x5c2fae(0xec)]?.[_0x45a59d]&&(_0x43d6cc['devDependencies'][_0x45a59d]=_0x540d17);}await a0_0x4ffdd1['writeFile'](_0x243434,JSON[_0x5c2fae(0x118)](_0x43d6cc,null,0x2)+'\x0a'),_0x4872b8['push'](_0x5c2fae(0xad)),_0x4872b8[_0x5c2fae(0xfc)](_0x5c2fae(0xf0));try{const {stdout:_0x3c8cbf,stderr:_0x14af82}=await exec(_0x5c2fae(0xeb),{'cwd':_0x49c42d,'timeout':RESOLVER_CONFIG['NPM_COMMAND_TIMEOUT'],'maxBuffer':0x400*0x400*0xa});if(_0x3c8cbf){const _0x800629=_0x3c8cbf['trim']()['split']('\x0a');_0x800629['length']>0xa?_0x4872b8[_0x5c2fae(0xfc)]('\x20\x20'+_0x800629['slice'](-0x5)['join'](_0x5c2fae(0xbd))):_0x4872b8['push']('\x20\x20'+_0x3c8cbf['trim']());}_0x14af82&&!_0x14af82[_0x5c2fae(0xdc)](_0x5c2fae(0xac))&&_0x4872b8['push'](_0x5c2fae(0xed)+_0x14af82[_0x5c2fae(0xb2)]());_0x4872b8['push'](_0x5c2fae(0xb1));try{const {stdout:_0x4b0f13}=await exec('npm\x20ls\x20--depth=0\x20--json',{'cwd':_0x49c42d,'timeout':0x7530}),_0x2e487c=JSON[_0x5c2fae(0x105)](_0x4b0f13);if(_0x2e487c['dependencies']){_0x4872b8['push'](_0x5c2fae(0xcb));for(const _0x2c0c3f of Object[_0x5c2fae(0xcc)](_0x479918)){_0x2e487c['dependencies'][_0x2c0c3f]&&_0x4872b8[_0x5c2fae(0xfc)](_0x5c2fae(0xbe)+_0x2c0c3f+'@'+_0x2e487c[_0x5c2fae(0xbf)][_0x2c0c3f]['version']);}}}catch(_0x209fb0){this['logger']?.[_0x5c2fae(0xa3)]('npm\x20ls\x20failed:',_0x209fb0['message']);}return{'success':!![],'mode':_0x47ba1a,'message':'Successfully\x20updated\x20'+Object[_0x5c2fae(0xcc)](_0x479918)[_0x5c2fae(0xbb)]+'\x20package(s)','statistics':{'totalDependencies':Object['keys'](_0x3f97db)[_0x5c2fae(0xbb)],'updatesAvailable':Object['keys'](_0x479918)[_0x5c2fae(0xbb)],'updatesApplied':Object['keys'](_0x479918)[_0x5c2fae(0xbb)],'errors':0x0},'updates':_0x479918,'backupCreated':_0x346708!==null,'backupPath':_0x346708,'output':_0x4872b8['join']('\x0a')};}catch(_0x4a978e){_0x4872b8['push'](_0x5c2fae(0xa4)+_0x4a978e['message']);if(_0x346708)try{await a0_0x4ffdd1['copyFile'](_0x346708,_0x243434),_0x4872b8[_0x5c2fae(0xfc)]('\uD83D\uDD04 Restored package.json from backup');}catch(_0x52609d){_0x4872b8[_0x5c2fae(0xfc)]('⚠️\x20\x20Failed\x20to\x20restore\x20backup');}return{'success':![],'mode':_0x47ba1a,'error':'npm\x20install\x20failed:\x20'+_0x4a978e['message'],'statistics':{'totalDependencies':Object[_0x5c2fae(0xcc)](_0x3f97db)['length'],'updatesAvailable':Object['keys'](_0x479918)['length'],'updatesApplied':0x0,'errors':0x1},'updates':_0x479918,'backupCreated':_0x346708!==null,'output':_0x4872b8['join']('\x0a')};}}else{if(_0x47ba1a==='fix'||_0x47ba1a===_0x5c2fae(0xe0))return _0x4872b8['push'](_0x5c2fae(0xdd)),{'success':!![],'mode':_0x47ba1a,'message':_0x5c2fae(0xe6),'statistics':{'totalDependencies':Object[_0x5c2fae(0xcc)](_0x3f97db)['length'],'updatesAvailable':0x0,'updatesApplied':0x0,'errors':0x0},'updates':{},'output':_0x4872b8[_0x5c2fae(0xd5)]('\x0a')};}}catch(_0x3ef6a0){return this['logger']?.['error'](_0x5c2fae(0xf5),_0x3ef6a0),{'success':![],'error':_0x3ef6a0['message'],'statistics':{'totalDependencies':0x0,'updatesAvailable':0x0,'updatesApplied':0x0,'errors':0x1},'output':_0x3ef6a0[_0x5c2fae(0xe1)]};}}}export default DependencyResolverTool;
|