@utaba/ucm-mcp-server 1.0.0
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/LICENSE +29 -0
- package/README.md +79 -0
- package/dist/clients/UcmApiClient.d.ts +53 -0
- package/dist/clients/UcmApiClient.js +297 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +68 -0
- package/dist/interfaces/ILogger.d.ts +8 -0
- package/dist/interfaces/ILogger.js +4 -0
- package/dist/interfaces/IMcpTool.d.ts +7 -0
- package/dist/interfaces/IMcpTool.js +3 -0
- package/dist/logging/ConsoleLogger.d.ts +16 -0
- package/dist/logging/ConsoleLogger.js +45 -0
- package/dist/logging/LoggerFactory.d.ts +9 -0
- package/dist/logging/LoggerFactory.js +12 -0
- package/dist/server/McpConfig.d.ts +26 -0
- package/dist/server/McpConfig.js +93 -0
- package/dist/server/McpHandler.d.ts +12 -0
- package/dist/server/McpHandler.js +69 -0
- package/dist/server/McpServer.d.ts +15 -0
- package/dist/server/McpServer.js +49 -0
- package/dist/server/ToolRegistry.d.ts +22 -0
- package/dist/server/ToolRegistry.js +85 -0
- package/dist/tools/artifacts/GetArtifactController.d.ts +34 -0
- package/dist/tools/artifacts/GetArtifactController.js +397 -0
- package/dist/tools/artifacts/GetLatestController.d.ts +39 -0
- package/dist/tools/artifacts/GetLatestController.js +469 -0
- package/dist/tools/artifacts/ListVersionsController.d.ts +43 -0
- package/dist/tools/artifacts/ListVersionsController.js +530 -0
- package/dist/tools/artifacts/PublishArtifactController.d.ts +37 -0
- package/dist/tools/artifacts/PublishArtifactController.js +605 -0
- package/dist/tools/base/BaseToolController.d.ts +16 -0
- package/dist/tools/base/BaseToolController.js +32 -0
- package/dist/tools/core/DeleteArtifactTool.d.ts +11 -0
- package/dist/tools/core/DeleteArtifactTool.js +82 -0
- package/dist/tools/core/GetArtifactTool.d.ts +13 -0
- package/dist/tools/core/GetArtifactTool.js +125 -0
- package/dist/tools/core/GetArtifactVersionsTool.d.ts +11 -0
- package/dist/tools/core/GetArtifactVersionsTool.js +63 -0
- package/dist/tools/core/GetChunkTool.d.ts +11 -0
- package/dist/tools/core/GetChunkTool.js +56 -0
- package/dist/tools/core/ListArtifactsTool.d.ts +11 -0
- package/dist/tools/core/ListArtifactsTool.js +84 -0
- package/dist/tools/core/PublishArtifactFromFileTool.d.ts +15 -0
- package/dist/tools/core/PublishArtifactFromFileTool.js +256 -0
- package/dist/tools/core/PublishArtifactTool.d.ts +13 -0
- package/dist/tools/core/PublishArtifactTool.js +197 -0
- package/dist/tools/discovery/BrowseCategoriesController.d.ts +25 -0
- package/dist/tools/discovery/BrowseCategoriesController.js +400 -0
- package/dist/tools/discovery/FindByPurposeController.d.ts +12 -0
- package/dist/tools/discovery/FindByPurposeController.js +131 -0
- package/dist/tools/discovery/ListAuthorsController.d.ts +20 -0
- package/dist/tools/discovery/ListAuthorsController.js +274 -0
- package/dist/tools/discovery/SearchArtifactsController.d.ts +14 -0
- package/dist/tools/discovery/SearchArtifactsController.js +226 -0
- package/dist/tools/list/ListNamespaceController.d.ts +1 -0
- package/dist/tools/list/ListNamespaceController.js +8 -0
- package/dist/tools/navigation/ExploreNamespaceController.d.ts +35 -0
- package/dist/tools/navigation/ExploreNamespaceController.js +548 -0
- package/dist/tools/utility/AuthorIndexTool.d.ts +11 -0
- package/dist/tools/utility/AuthorIndexTool.js +48 -0
- package/dist/tools/utility/HealthCheckController.d.ts +11 -0
- package/dist/tools/utility/HealthCheckController.js +56 -0
- package/dist/tools/utility/ListRepositoriesTool.d.ts +11 -0
- package/dist/tools/utility/ListRepositoriesTool.js +70 -0
- package/dist/tools/utility/QuickstartTool.d.ts +11 -0
- package/dist/tools/utility/QuickstartTool.js +36 -0
- package/dist/tools/utility/ValidatePathController.d.ts +30 -0
- package/dist/tools/utility/ValidatePathController.js +465 -0
- package/dist/types/UcmApiTypes.d.ts +40 -0
- package/dist/types/UcmApiTypes.js +4 -0
- package/dist/utils/McpErrorHandler.d.ts +25 -0
- package/dist/utils/McpErrorHandler.js +67 -0
- package/dist/utils/PathUtils.d.ts +61 -0
- package/dist/utils/PathUtils.js +178 -0
- package/dist/utils/ResponseChunker.d.ts +25 -0
- package/dist/utils/ResponseChunker.js +79 -0
- package/dist/utils/ValidationUtils.d.ts +10 -0
- package/dist/utils/ValidationUtils.js +50 -0
- package/package.json +37 -0
- package/package.json.backup +37 -0
|
@@ -0,0 +1,530 @@
|
|
|
1
|
+
import { BaseToolController } from '../base/BaseToolController.js';
|
|
2
|
+
import { ValidationUtils } from '../../utils/ValidationUtils.js';
|
|
3
|
+
import { parsePath } from '../../utils/PathUtils.js';
|
|
4
|
+
export class ListVersionsController extends BaseToolController {
|
|
5
|
+
constructor(ucmClient, logger) {
|
|
6
|
+
super(ucmClient, logger);
|
|
7
|
+
}
|
|
8
|
+
get name() {
|
|
9
|
+
return 'mcp_ucm_list_versions';
|
|
10
|
+
}
|
|
11
|
+
get description() {
|
|
12
|
+
return 'List all available versions of a UCM artifact with detailed version information and comparison';
|
|
13
|
+
}
|
|
14
|
+
get inputSchema() {
|
|
15
|
+
return {
|
|
16
|
+
type: 'object',
|
|
17
|
+
properties: {
|
|
18
|
+
artifactPath: {
|
|
19
|
+
type: 'string',
|
|
20
|
+
description: 'Artifact path without version (e.g., "utaba/commands/create-user/typescript" or "utaba/commands/create-user")',
|
|
21
|
+
minLength: 5,
|
|
22
|
+
maxLength: 150
|
|
23
|
+
},
|
|
24
|
+
includeMetadata: {
|
|
25
|
+
type: 'boolean',
|
|
26
|
+
default: false,
|
|
27
|
+
description: 'Include detailed metadata for each version'
|
|
28
|
+
},
|
|
29
|
+
includeChangeSummary: {
|
|
30
|
+
type: 'boolean',
|
|
31
|
+
default: true,
|
|
32
|
+
description: 'Include summary of changes between versions'
|
|
33
|
+
},
|
|
34
|
+
includeStats: {
|
|
35
|
+
type: 'boolean',
|
|
36
|
+
default: false,
|
|
37
|
+
description: 'Include download and usage statistics for each version'
|
|
38
|
+
},
|
|
39
|
+
sortBy: {
|
|
40
|
+
type: 'string',
|
|
41
|
+
enum: ['version', 'date', 'downloads', 'rating'],
|
|
42
|
+
default: 'version',
|
|
43
|
+
description: 'Sort versions by specified criteria'
|
|
44
|
+
},
|
|
45
|
+
sortOrder: {
|
|
46
|
+
type: 'string',
|
|
47
|
+
enum: ['asc', 'desc'],
|
|
48
|
+
default: 'desc',
|
|
49
|
+
description: 'Sort order (newest first by default)'
|
|
50
|
+
},
|
|
51
|
+
limit: {
|
|
52
|
+
type: 'number',
|
|
53
|
+
minimum: 1,
|
|
54
|
+
maximum: 100,
|
|
55
|
+
default: 20,
|
|
56
|
+
description: 'Maximum number of versions to return'
|
|
57
|
+
},
|
|
58
|
+
sinceVersion: {
|
|
59
|
+
type: 'string',
|
|
60
|
+
pattern: '^[0-9]+\\.[0-9]+\\.[0-9]+',
|
|
61
|
+
description: 'Only show versions newer than this version'
|
|
62
|
+
},
|
|
63
|
+
versionPattern: {
|
|
64
|
+
type: 'string',
|
|
65
|
+
description: 'Filter versions matching this pattern (e.g., "1.*", "*.0.0")'
|
|
66
|
+
}
|
|
67
|
+
},
|
|
68
|
+
required: ['artifactPath']
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
async handleExecute(params) {
|
|
72
|
+
const { artifactPath, includeMetadata = false, includeChangeSummary = true, includeStats = false, sortBy = 'version', sortOrder = 'desc', limit = 20, sinceVersion, versionPattern } = params;
|
|
73
|
+
// Validate the artifact path (should not include version)
|
|
74
|
+
this.validateBasePath(artifactPath);
|
|
75
|
+
if (sinceVersion) {
|
|
76
|
+
ValidationUtils.validateVersion(sinceVersion);
|
|
77
|
+
}
|
|
78
|
+
this.logger.debug('ListVersionsController', `Listing versions for: ${artifactPath}`);
|
|
79
|
+
try {
|
|
80
|
+
// Parse the path to get component parts
|
|
81
|
+
const parsed = parsePath(artifactPath);
|
|
82
|
+
// Get all versions from UCM API
|
|
83
|
+
const allVersions = await this.ucmClient.getArtifactVersions(parsed.author, parsed.category, parsed.subcategory);
|
|
84
|
+
if (!allVersions || allVersions.length === 0) {
|
|
85
|
+
return {
|
|
86
|
+
artifactPath,
|
|
87
|
+
versions: [],
|
|
88
|
+
totalVersions: 0,
|
|
89
|
+
message: 'No versions found for this artifact'
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
// Apply filters
|
|
93
|
+
let filteredVersions = allVersions;
|
|
94
|
+
if (sinceVersion) {
|
|
95
|
+
filteredVersions = this.filterVersionsSince(filteredVersions, sinceVersion);
|
|
96
|
+
}
|
|
97
|
+
if (versionPattern) {
|
|
98
|
+
filteredVersions = this.filterVersionsByPattern(filteredVersions, versionPattern);
|
|
99
|
+
}
|
|
100
|
+
// Process and enrich version data
|
|
101
|
+
const enrichedVersions = await this.enrichVersionData(filteredVersions, { includeMetadata, includeChangeSummary, includeStats });
|
|
102
|
+
// Sort versions
|
|
103
|
+
const sortedVersions = this.sortVersions(enrichedVersions, sortBy, sortOrder);
|
|
104
|
+
// Apply limit
|
|
105
|
+
const limitedVersions = sortedVersions.slice(0, limit);
|
|
106
|
+
// Build response
|
|
107
|
+
const response = {
|
|
108
|
+
artifactPath,
|
|
109
|
+
versions: limitedVersions,
|
|
110
|
+
pagination: {
|
|
111
|
+
total: filteredVersions.length,
|
|
112
|
+
returned: limitedVersions.length,
|
|
113
|
+
hasMore: filteredVersions.length > limit
|
|
114
|
+
},
|
|
115
|
+
sorting: {
|
|
116
|
+
sortBy,
|
|
117
|
+
sortOrder
|
|
118
|
+
},
|
|
119
|
+
filters: {
|
|
120
|
+
sinceVersion,
|
|
121
|
+
versionPattern
|
|
122
|
+
},
|
|
123
|
+
summary: this.generateVersionSummary(allVersions, filteredVersions),
|
|
124
|
+
versionAnalysis: this.analyzeVersionHistory(sortedVersions),
|
|
125
|
+
recommendations: this.generateVersionRecommendations(sortedVersions),
|
|
126
|
+
metadata: {
|
|
127
|
+
timestamp: new Date().toISOString(),
|
|
128
|
+
includeMetadata,
|
|
129
|
+
includeChangeSummary,
|
|
130
|
+
includeStats
|
|
131
|
+
}
|
|
132
|
+
};
|
|
133
|
+
this.logger.info('ListVersionsController', `Listed ${limitedVersions.length} versions (${filteredVersions.length} total)`);
|
|
134
|
+
return response;
|
|
135
|
+
}
|
|
136
|
+
catch (error) {
|
|
137
|
+
this.logger.error('ListVersionsController', `Failed to list versions for: ${artifactPath}`, '', error);
|
|
138
|
+
throw error;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
validateBasePath(path) {
|
|
142
|
+
// Ensure path doesn't end with a version number
|
|
143
|
+
const pathParts = path.split('/');
|
|
144
|
+
const lastPart = pathParts[pathParts.length - 1];
|
|
145
|
+
if (lastPart.match(/^[0-9]+\.[0-9]+\.[0-9]+/)) {
|
|
146
|
+
throw this.formatError(new Error('Artifact path should not include version number'));
|
|
147
|
+
}
|
|
148
|
+
if (pathParts.length < 3) {
|
|
149
|
+
throw this.formatError(new Error('Artifact path must include at least author/category/subcategory'));
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
filterVersionsSince(versions, sinceVersion) {
|
|
153
|
+
return versions.filter(version => {
|
|
154
|
+
const versionNumber = version.metadata?.version || '0.0.0';
|
|
155
|
+
return this.compareVersions(versionNumber, sinceVersion) > 0;
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
filterVersionsByPattern(versions, pattern) {
|
|
159
|
+
const regex = new RegExp(pattern.replace(/\*/g, '.*').replace(/\./g, '\\.'));
|
|
160
|
+
return versions.filter(version => {
|
|
161
|
+
const versionNumber = version.metadata?.version || '0.0.0';
|
|
162
|
+
return regex.test(versionNumber);
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
async enrichVersionData(versions, options) {
|
|
166
|
+
const { includeMetadata, includeChangeSummary, includeStats } = options;
|
|
167
|
+
const enrichedVersions = [];
|
|
168
|
+
for (let i = 0; i < versions.length; i++) {
|
|
169
|
+
const version = versions[i];
|
|
170
|
+
const enriched = {
|
|
171
|
+
version: version.metadata?.version || 'unknown',
|
|
172
|
+
path: version.path,
|
|
173
|
+
publishedAt: version.publishedAt,
|
|
174
|
+
lastUpdated: version.lastUpdated,
|
|
175
|
+
contractVersion: version.metadata?.contractVersion,
|
|
176
|
+
// Basic version information
|
|
177
|
+
releaseType: this.determineReleaseType(version.metadata?.version),
|
|
178
|
+
isPreRelease: this.isPreRelease(version.metadata?.version),
|
|
179
|
+
lifecycle: this.determineLifecycleStage(version),
|
|
180
|
+
stability: this.assessVersionStability(version)
|
|
181
|
+
};
|
|
182
|
+
// Include metadata if requested
|
|
183
|
+
if (includeMetadata && version.metadata) {
|
|
184
|
+
enriched.metadata = {
|
|
185
|
+
...version.metadata,
|
|
186
|
+
qualityScore: this.calculateQualityScore(version.metadata),
|
|
187
|
+
completeness: this.assessMetadataCompleteness(version.metadata)
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
// Include change summary if requested
|
|
191
|
+
if (includeChangeSummary) {
|
|
192
|
+
const previousVersion = i < versions.length - 1 ? versions[i + 1] : null;
|
|
193
|
+
enriched.changeSummary = await this.generateChangeSummary(version, previousVersion);
|
|
194
|
+
}
|
|
195
|
+
// Include statistics if requested
|
|
196
|
+
if (includeStats) {
|
|
197
|
+
enriched.statistics = {
|
|
198
|
+
downloadCount: this.getDownloadCount(version),
|
|
199
|
+
rating: this.calculateRating(version),
|
|
200
|
+
usageMetrics: this.getUsageMetrics(version),
|
|
201
|
+
adoptionRate: this.calculateAdoptionRate(version, versions)
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
enrichedVersions.push(enriched);
|
|
205
|
+
}
|
|
206
|
+
return enrichedVersions;
|
|
207
|
+
}
|
|
208
|
+
sortVersions(versions, sortBy, sortOrder) {
|
|
209
|
+
return versions.sort((a, b) => {
|
|
210
|
+
let comparison = 0;
|
|
211
|
+
switch (sortBy) {
|
|
212
|
+
case 'version':
|
|
213
|
+
comparison = this.compareVersions(a.version, b.version);
|
|
214
|
+
break;
|
|
215
|
+
case 'date':
|
|
216
|
+
const aDate = new Date(a.publishedAt || 0);
|
|
217
|
+
const bDate = new Date(b.publishedAt || 0);
|
|
218
|
+
comparison = aDate.getTime() - bDate.getTime();
|
|
219
|
+
break;
|
|
220
|
+
case 'downloads':
|
|
221
|
+
const aDownloads = a.statistics?.downloadCount || 0;
|
|
222
|
+
const bDownloads = b.statistics?.downloadCount || 0;
|
|
223
|
+
comparison = aDownloads - bDownloads;
|
|
224
|
+
break;
|
|
225
|
+
case 'rating':
|
|
226
|
+
const aRating = a.statistics?.rating || 0;
|
|
227
|
+
const bRating = b.statistics?.rating || 0;
|
|
228
|
+
comparison = aRating - bRating;
|
|
229
|
+
break;
|
|
230
|
+
default:
|
|
231
|
+
comparison = this.compareVersions(a.version, b.version);
|
|
232
|
+
}
|
|
233
|
+
return sortOrder === 'desc' ? -comparison : comparison;
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
generateVersionSummary(allVersions, filteredVersions) {
|
|
237
|
+
const versionNumbers = allVersions.map(v => v.metadata?.version || '0.0.0');
|
|
238
|
+
const latest = this.getLatestVersion(versionNumbers);
|
|
239
|
+
const oldest = this.getOldestVersion(versionNumbers);
|
|
240
|
+
return {
|
|
241
|
+
totalVersions: allVersions.length,
|
|
242
|
+
filteredVersions: filteredVersions.length,
|
|
243
|
+
latestVersion: latest,
|
|
244
|
+
oldestVersion: oldest,
|
|
245
|
+
versionSpan: this.calculateVersionSpan(oldest, latest),
|
|
246
|
+
releaseFrequency: this.calculateReleaseFrequency(allVersions),
|
|
247
|
+
averageTimeBetweenReleases: this.calculateAverageTimeBetweenReleases(allVersions)
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
analyzeVersionHistory(versions) {
|
|
251
|
+
const analysis = {
|
|
252
|
+
patterns: {
|
|
253
|
+
majorReleases: 0,
|
|
254
|
+
minorReleases: 0,
|
|
255
|
+
patchReleases: 0,
|
|
256
|
+
preReleases: 0
|
|
257
|
+
},
|
|
258
|
+
trends: {
|
|
259
|
+
releaseVelocity: 'stable',
|
|
260
|
+
breakingChangeFrequency: 'low',
|
|
261
|
+
stabilityTrend: 'improving'
|
|
262
|
+
},
|
|
263
|
+
insights: []
|
|
264
|
+
};
|
|
265
|
+
// Analyze release patterns
|
|
266
|
+
versions.forEach(version => {
|
|
267
|
+
switch (version.releaseType) {
|
|
268
|
+
case 'major':
|
|
269
|
+
analysis.patterns.majorReleases++;
|
|
270
|
+
break;
|
|
271
|
+
case 'minor':
|
|
272
|
+
analysis.patterns.minorReleases++;
|
|
273
|
+
break;
|
|
274
|
+
case 'patch':
|
|
275
|
+
analysis.patterns.patchReleases++;
|
|
276
|
+
break;
|
|
277
|
+
default:
|
|
278
|
+
if (version.isPreRelease) {
|
|
279
|
+
analysis.patterns.preReleases++;
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
});
|
|
283
|
+
// Generate insights
|
|
284
|
+
if (analysis.patterns.majorReleases > versions.length * 0.3) {
|
|
285
|
+
analysis.insights.push('Frequent major releases - API may be evolving rapidly');
|
|
286
|
+
}
|
|
287
|
+
if (analysis.patterns.patchReleases > versions.length * 0.6) {
|
|
288
|
+
analysis.insights.push('High patch release frequency - good maintenance practices');
|
|
289
|
+
}
|
|
290
|
+
if (analysis.patterns.preReleases > 0) {
|
|
291
|
+
analysis.insights.push('Pre-release versions available - bleeding edge features');
|
|
292
|
+
}
|
|
293
|
+
return analysis;
|
|
294
|
+
}
|
|
295
|
+
generateVersionRecommendations(versions) {
|
|
296
|
+
const recommendations = {
|
|
297
|
+
recommended: null,
|
|
298
|
+
alternatives: [],
|
|
299
|
+
warnings: []
|
|
300
|
+
};
|
|
301
|
+
if (versions.length === 0) {
|
|
302
|
+
return recommendations;
|
|
303
|
+
}
|
|
304
|
+
// Find recommended version (latest stable)
|
|
305
|
+
const stableVersions = versions.filter(v => !v.isPreRelease && v.stability !== 'experimental');
|
|
306
|
+
if (stableVersions.length > 0) {
|
|
307
|
+
recommendations.recommended = {
|
|
308
|
+
version: stableVersions[0].version,
|
|
309
|
+
reason: 'Latest stable version',
|
|
310
|
+
confidence: 'high'
|
|
311
|
+
};
|
|
312
|
+
}
|
|
313
|
+
else {
|
|
314
|
+
recommendations.recommended = {
|
|
315
|
+
version: versions[0].version,
|
|
316
|
+
reason: 'Latest available version',
|
|
317
|
+
confidence: 'medium'
|
|
318
|
+
};
|
|
319
|
+
}
|
|
320
|
+
// Find alternatives
|
|
321
|
+
const majorVersions = this.groupByMajorVersion(versions);
|
|
322
|
+
for (const [major, versionList] of Object.entries(majorVersions)) {
|
|
323
|
+
if (versionList.length > 0 && versionList[0].version !== recommendations.recommended.version) {
|
|
324
|
+
recommendations.alternatives.push({
|
|
325
|
+
version: versionList[0].version,
|
|
326
|
+
reason: `Latest in v${major}.x series`,
|
|
327
|
+
stability: versionList[0].stability
|
|
328
|
+
});
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
// Generate warnings
|
|
332
|
+
const latestVersion = versions[0];
|
|
333
|
+
if (latestVersion?.isPreRelease) {
|
|
334
|
+
recommendations.warnings.push('Latest version is a pre-release - use with caution in production');
|
|
335
|
+
}
|
|
336
|
+
if (latestVersion?.lifecycle === 'legacy') {
|
|
337
|
+
recommendations.warnings.push('This artifact may be deprecated - consider alternatives');
|
|
338
|
+
}
|
|
339
|
+
return recommendations;
|
|
340
|
+
}
|
|
341
|
+
async generateChangeSummary(version, previousVersion) {
|
|
342
|
+
if (!previousVersion) {
|
|
343
|
+
return {
|
|
344
|
+
isFirst: true,
|
|
345
|
+
message: 'Initial version'
|
|
346
|
+
};
|
|
347
|
+
}
|
|
348
|
+
const summary = {
|
|
349
|
+
isFirst: false,
|
|
350
|
+
previousVersion: previousVersion.metadata?.version,
|
|
351
|
+
changeType: this.determineChangeType(previousVersion.metadata?.version, version.metadata?.version),
|
|
352
|
+
timespan: this.calculateTimespan(previousVersion.publishedAt, version.publishedAt),
|
|
353
|
+
breaking: this.hasBreakingChanges(previousVersion, version),
|
|
354
|
+
features: this.detectNewFeatures(previousVersion, version),
|
|
355
|
+
improvements: this.detectImprovements(previousVersion, version),
|
|
356
|
+
fixes: this.detectFixes(previousVersion, version)
|
|
357
|
+
};
|
|
358
|
+
return summary;
|
|
359
|
+
}
|
|
360
|
+
// Helper methods
|
|
361
|
+
compareVersions(version1, version2) {
|
|
362
|
+
const v1Parts = version1.split('.').map(Number);
|
|
363
|
+
const v2Parts = version2.split('.').map(Number);
|
|
364
|
+
for (let i = 0; i < Math.max(v1Parts.length, v2Parts.length); i++) {
|
|
365
|
+
const v1Part = v1Parts[i] || 0;
|
|
366
|
+
const v2Part = v2Parts[i] || 0;
|
|
367
|
+
if (v1Part !== v2Part) {
|
|
368
|
+
return v1Part - v2Part;
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
return 0;
|
|
372
|
+
}
|
|
373
|
+
determineReleaseType(version) {
|
|
374
|
+
if (!version)
|
|
375
|
+
return 'unknown';
|
|
376
|
+
const [major, minor, patch] = version.split('.').map(Number);
|
|
377
|
+
if (major > 0 && minor === 0 && patch === 0)
|
|
378
|
+
return 'major';
|
|
379
|
+
if (minor > 0 && patch === 0)
|
|
380
|
+
return 'minor';
|
|
381
|
+
return 'patch';
|
|
382
|
+
}
|
|
383
|
+
isPreRelease(version) {
|
|
384
|
+
return !!(version && (version.includes('alpha') || version.includes('beta') || version.includes('rc')));
|
|
385
|
+
}
|
|
386
|
+
determineLifecycleStage(version) {
|
|
387
|
+
const publishedAt = new Date(version.publishedAt || Date.now());
|
|
388
|
+
const daysSincePublished = (Date.now() - publishedAt.getTime()) / (1000 * 60 * 60 * 24);
|
|
389
|
+
if (daysSincePublished < 30)
|
|
390
|
+
return 'new';
|
|
391
|
+
if (daysSincePublished < 365)
|
|
392
|
+
return 'active';
|
|
393
|
+
if (daysSincePublished < 1095)
|
|
394
|
+
return 'mature';
|
|
395
|
+
return 'legacy';
|
|
396
|
+
}
|
|
397
|
+
assessVersionStability(version) {
|
|
398
|
+
if (this.isPreRelease(version.metadata?.version))
|
|
399
|
+
return 'experimental';
|
|
400
|
+
if (this.determineLifecycleStage(version) === 'new')
|
|
401
|
+
return 'testing';
|
|
402
|
+
return 'stable';
|
|
403
|
+
}
|
|
404
|
+
calculateQualityScore(metadata) {
|
|
405
|
+
let score = 50;
|
|
406
|
+
if (metadata.description?.length > 20)
|
|
407
|
+
score += 20;
|
|
408
|
+
if (metadata.tags?.length > 0)
|
|
409
|
+
score += 10;
|
|
410
|
+
if (metadata.dependencies)
|
|
411
|
+
score += 10;
|
|
412
|
+
if (metadata.contractVersion)
|
|
413
|
+
score += 10;
|
|
414
|
+
return Math.min(score, 100);
|
|
415
|
+
}
|
|
416
|
+
assessMetadataCompleteness(metadata) {
|
|
417
|
+
const fields = ['name', 'description', 'author', 'category', 'version'];
|
|
418
|
+
const presentFields = fields.filter(field => metadata[field]);
|
|
419
|
+
return Math.round((presentFields.length / fields.length) * 100);
|
|
420
|
+
}
|
|
421
|
+
getLatestVersion(versions) {
|
|
422
|
+
return versions.sort((a, b) => this.compareVersions(b, a))[0];
|
|
423
|
+
}
|
|
424
|
+
getOldestVersion(versions) {
|
|
425
|
+
return versions.sort((a, b) => this.compareVersions(a, b))[0];
|
|
426
|
+
}
|
|
427
|
+
calculateVersionSpan(oldest, latest) {
|
|
428
|
+
const comparison = this.compareVersions(latest, oldest);
|
|
429
|
+
if (comparison === 0)
|
|
430
|
+
return 'Single version';
|
|
431
|
+
const [oldMajor] = oldest.split('.').map(Number);
|
|
432
|
+
const [newMajor] = latest.split('.').map(Number);
|
|
433
|
+
const majorSpan = newMajor - oldMajor;
|
|
434
|
+
if (majorSpan > 0)
|
|
435
|
+
return `${majorSpan} major version${majorSpan > 1 ? 's' : ''}`;
|
|
436
|
+
return 'Minor/patch versions';
|
|
437
|
+
}
|
|
438
|
+
calculateReleaseFrequency(versions) {
|
|
439
|
+
if (versions.length < 2)
|
|
440
|
+
return 'insufficient-data';
|
|
441
|
+
const timespan = this.calculateAverageTimeBetweenReleases(versions);
|
|
442
|
+
if (timespan < 30)
|
|
443
|
+
return 'high';
|
|
444
|
+
if (timespan < 90)
|
|
445
|
+
return 'moderate';
|
|
446
|
+
return 'low';
|
|
447
|
+
}
|
|
448
|
+
calculateAverageTimeBetweenReleases(versions) {
|
|
449
|
+
if (versions.length < 2)
|
|
450
|
+
return 0;
|
|
451
|
+
const dates = versions
|
|
452
|
+
.map(v => new Date(v.publishedAt || 0))
|
|
453
|
+
.sort((a, b) => a.getTime() - b.getTime());
|
|
454
|
+
let totalDays = 0;
|
|
455
|
+
for (let i = 1; i < dates.length; i++) {
|
|
456
|
+
totalDays += (dates[i].getTime() - dates[i - 1].getTime()) / (1000 * 60 * 60 * 24);
|
|
457
|
+
}
|
|
458
|
+
return totalDays / (dates.length - 1);
|
|
459
|
+
}
|
|
460
|
+
groupByMajorVersion(versions) {
|
|
461
|
+
const groups = {};
|
|
462
|
+
versions.forEach(version => {
|
|
463
|
+
const [major] = version.version.split('.');
|
|
464
|
+
if (!groups[major])
|
|
465
|
+
groups[major] = [];
|
|
466
|
+
groups[major].push(version);
|
|
467
|
+
});
|
|
468
|
+
return groups;
|
|
469
|
+
}
|
|
470
|
+
determineChangeType(oldVersion, newVersion) {
|
|
471
|
+
const comparison = this.compareVersions(newVersion, oldVersion);
|
|
472
|
+
const [oldMajor, oldMinor] = oldVersion.split('.').map(Number);
|
|
473
|
+
const [newMajor, newMinor] = newVersion.split('.').map(Number);
|
|
474
|
+
if (newMajor > oldMajor)
|
|
475
|
+
return 'major';
|
|
476
|
+
if (newMinor > oldMinor)
|
|
477
|
+
return 'minor';
|
|
478
|
+
return 'patch';
|
|
479
|
+
}
|
|
480
|
+
calculateTimespan(oldDate, newDate) {
|
|
481
|
+
const old = new Date(oldDate || 0);
|
|
482
|
+
const current = new Date(newDate || Date.now());
|
|
483
|
+
const diffMs = current.getTime() - old.getTime();
|
|
484
|
+
const diffDays = Math.floor(diffMs / (1000 * 60 * 60 * 24));
|
|
485
|
+
if (diffDays < 1)
|
|
486
|
+
return 'same day';
|
|
487
|
+
if (diffDays < 7)
|
|
488
|
+
return `${diffDays} days`;
|
|
489
|
+
if (diffDays < 30)
|
|
490
|
+
return `${Math.floor(diffDays / 7)} weeks`;
|
|
491
|
+
if (diffDays < 365)
|
|
492
|
+
return `${Math.floor(diffDays / 30)} months`;
|
|
493
|
+
return `${Math.floor(diffDays / 365)} years`;
|
|
494
|
+
}
|
|
495
|
+
// Simulated methods for demo
|
|
496
|
+
hasBreakingChanges(oldVersion, newVersion) {
|
|
497
|
+
return oldVersion.metadata?.contractVersion !== newVersion.metadata?.contractVersion;
|
|
498
|
+
}
|
|
499
|
+
detectNewFeatures(oldVersion, newVersion) {
|
|
500
|
+
const oldTags = oldVersion.metadata?.tags || [];
|
|
501
|
+
const newTags = newVersion.metadata?.tags || [];
|
|
502
|
+
return newTags.filter((tag) => !oldTags.includes(tag));
|
|
503
|
+
}
|
|
504
|
+
detectImprovements(oldVersion, newVersion) {
|
|
505
|
+
const improvements = [];
|
|
506
|
+
if ((newVersion.metadata?.description?.length || 0) > (oldVersion.metadata?.description?.length || 0)) {
|
|
507
|
+
improvements.push('Enhanced documentation');
|
|
508
|
+
}
|
|
509
|
+
return improvements;
|
|
510
|
+
}
|
|
511
|
+
detectFixes(oldVersion, newVersion) {
|
|
512
|
+
return ['General bug fixes and improvements']; // Simulated
|
|
513
|
+
}
|
|
514
|
+
getDownloadCount(version) {
|
|
515
|
+
return Math.floor(Math.random() * 1000); // Simulated
|
|
516
|
+
}
|
|
517
|
+
calculateRating(version) {
|
|
518
|
+
return 3.0 + Math.random() * 2; // Simulated
|
|
519
|
+
}
|
|
520
|
+
getUsageMetrics(version) {
|
|
521
|
+
return {
|
|
522
|
+
activeUsers: Math.floor(Math.random() * 100),
|
|
523
|
+
lastAccessed: new Date().toISOString()
|
|
524
|
+
};
|
|
525
|
+
}
|
|
526
|
+
calculateAdoptionRate(version, allVersions) {
|
|
527
|
+
return Math.random(); // Simulated
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
//# sourceMappingURL=ListVersionsController.js.map
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { BaseToolController } from '../base/BaseToolController.js';
|
|
2
|
+
import { UcmApiClient } from '../../clients/UcmApiClient.js';
|
|
3
|
+
import { ILogger } from '../../interfaces/ILogger.js';
|
|
4
|
+
export declare class PublishArtifactController extends BaseToolController {
|
|
5
|
+
constructor(ucmClient: UcmApiClient, logger: ILogger);
|
|
6
|
+
get name(): string;
|
|
7
|
+
get description(): string;
|
|
8
|
+
get inputSchema(): any;
|
|
9
|
+
protected handleExecute(params: any): Promise<any>;
|
|
10
|
+
private validatePublishRequest;
|
|
11
|
+
private performPrePublishValidation;
|
|
12
|
+
private handleExistingArtifact;
|
|
13
|
+
private preparePublishData;
|
|
14
|
+
private performPostPublishProcessing;
|
|
15
|
+
private validateContent;
|
|
16
|
+
private performSecurityScan;
|
|
17
|
+
private validateDependencies;
|
|
18
|
+
private performQualityChecks;
|
|
19
|
+
private parseArtifactPath;
|
|
20
|
+
private extractAuthorFromPath;
|
|
21
|
+
private extractCategoryFromPath;
|
|
22
|
+
private extractTechnologyFromMetadata;
|
|
23
|
+
private calculateContentHash;
|
|
24
|
+
private detectContentType;
|
|
25
|
+
private detectLanguageFromContent;
|
|
26
|
+
private isCodeContent;
|
|
27
|
+
private validateSyntax;
|
|
28
|
+
private generateDocumentation;
|
|
29
|
+
private buildViewUrl;
|
|
30
|
+
private buildDownloadUrl;
|
|
31
|
+
private buildApiUrl;
|
|
32
|
+
private indexForSearch;
|
|
33
|
+
private updateCaches;
|
|
34
|
+
private sendMaintainerNotifications;
|
|
35
|
+
private recordPublishAnalytics;
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=PublishArtifactController.d.ts.map
|