@entro314labs/ai-changelog-generator 3.6.1 → 3.7.1
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/manifest.json +13 -1
- package/package.json +10 -10
- package/src/application/orchestrators/changelog.orchestrator.js +28 -2
- package/src/application/services/application.service.js +8 -2
- package/src/domains/changelog/changelog.service.js +5 -2
- package/src/domains/git/git-manager.js +144 -2
- package/src/domains/git/git.service.js +22 -2
- package/src/infrastructure/cli/cli.controller.js +442 -6
- package/src/shared/utils/utils.js +0 -18
- package/src/domains/changelog/workspace-changelog.service.js +0 -566
|
@@ -1,566 +0,0 @@
|
|
|
1
|
-
import colors from '../../shared/constants/colors.js'
|
|
2
|
-
import { getWorkingDirectoryChanges } from '../../shared/utils/utils.js'
|
|
3
|
-
import { ChangelogService } from './changelog.service.js'
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* WorkspaceChangelogService extends ChangelogService with workspace-specific functionality
|
|
7
|
-
* for analyzing uncommitted changes and workspace state
|
|
8
|
-
*
|
|
9
|
-
* @deprecated This class is being phased out. The workspace changelog logic has been
|
|
10
|
-
* consolidated into ChangelogService. This class is maintained for backward compatibility
|
|
11
|
-
* with existing tests but should not be used in new code.
|
|
12
|
-
*/
|
|
13
|
-
export class WorkspaceChangelogService extends ChangelogService {
|
|
14
|
-
constructor(gitService, aiAnalysisService, analysisEngine = null, configManager = null) {
|
|
15
|
-
super(gitService, aiAnalysisService, analysisEngine, configManager)
|
|
16
|
-
this.workspaceMetrics = {
|
|
17
|
-
unstagedFiles: 0,
|
|
18
|
-
stagedFiles: 0,
|
|
19
|
-
untrackedFiles: 0,
|
|
20
|
-
modifiedLines: 0,
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Analyze workspace changes without committing
|
|
26
|
-
* @returns {Promise<Object>} Workspace analysis results
|
|
27
|
-
*/
|
|
28
|
-
async analyzeWorkspaceChanges() {
|
|
29
|
-
console.log(colors.processingMessage('🔍 Analyzing workspace changes...'))
|
|
30
|
-
|
|
31
|
-
try {
|
|
32
|
-
// Get git status information using utility function
|
|
33
|
-
const changes = getWorkingDirectoryChanges()
|
|
34
|
-
|
|
35
|
-
// Categorize changes
|
|
36
|
-
const status = {
|
|
37
|
-
staged: [],
|
|
38
|
-
unstaged: [],
|
|
39
|
-
untracked: [],
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
changes.forEach((change) => {
|
|
43
|
-
const statusCode = change.status || '??'
|
|
44
|
-
if (statusCode.startsWith('??')) {
|
|
45
|
-
status.untracked.push(change.filePath)
|
|
46
|
-
} else if (statusCode[0] !== ' ' && statusCode[0] !== '?') {
|
|
47
|
-
status.staged.push(change.filePath)
|
|
48
|
-
} else {
|
|
49
|
-
status.unstaged.push(change.filePath)
|
|
50
|
-
}
|
|
51
|
-
})
|
|
52
|
-
|
|
53
|
-
// Update workspace metrics
|
|
54
|
-
this.workspaceMetrics.unstagedFiles = status.unstaged?.length || 0
|
|
55
|
-
this.workspaceMetrics.stagedFiles = status.staged?.length || 0
|
|
56
|
-
this.workspaceMetrics.untrackedFiles = status.untracked?.length || 0
|
|
57
|
-
|
|
58
|
-
// Get detailed diff for staged/unstaged changes (empty for now)
|
|
59
|
-
const diff = ''
|
|
60
|
-
|
|
61
|
-
// Use analysis engine if available
|
|
62
|
-
let analysis = null
|
|
63
|
-
if (this.analysisEngine) {
|
|
64
|
-
analysis = await this.analysisEngine.analyzeCurrentChanges()
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
return {
|
|
68
|
-
status,
|
|
69
|
-
diff,
|
|
70
|
-
analysis,
|
|
71
|
-
metrics: this.workspaceMetrics,
|
|
72
|
-
}
|
|
73
|
-
} catch (error) {
|
|
74
|
-
console.error(colors.errorMessage(`Failed to analyze workspace: ${error.message}`))
|
|
75
|
-
throw error
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
/**
|
|
80
|
-
* Generate changelog preview for workspace changes
|
|
81
|
-
* @returns {Promise<string>} Preview changelog content
|
|
82
|
-
*/
|
|
83
|
-
async generateWorkspacePreview() {
|
|
84
|
-
console.log(colors.processingMessage('📝 Generating workspace preview...'))
|
|
85
|
-
|
|
86
|
-
const workspaceData = await this.analyzeWorkspaceChanges()
|
|
87
|
-
|
|
88
|
-
if (!workspaceData.analysis || workspaceData.analysis.changes.length === 0) {
|
|
89
|
-
return colors.infoMessage('No significant workspace changes detected.')
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
// Generate preview using parent class methods
|
|
93
|
-
const previewContent = await this.generateChangelogFromAnalysis(workspaceData.analysis)
|
|
94
|
-
|
|
95
|
-
return previewContent
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
/**
|
|
99
|
-
* Get workspace statistics
|
|
100
|
-
* @returns {Object} Workspace statistics
|
|
101
|
-
*/
|
|
102
|
-
getWorkspaceStats() {
|
|
103
|
-
return {
|
|
104
|
-
...this.workspaceMetrics,
|
|
105
|
-
hasChanges: this.hasWorkspaceChanges(),
|
|
106
|
-
summary: this.getWorkspaceSummary(),
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
/**
|
|
111
|
-
* Check if workspace has any changes
|
|
112
|
-
* @returns {boolean} True if workspace has changes
|
|
113
|
-
*/
|
|
114
|
-
hasWorkspaceChanges() {
|
|
115
|
-
return (
|
|
116
|
-
this.workspaceMetrics.unstagedFiles > 0 ||
|
|
117
|
-
this.workspaceMetrics.stagedFiles > 0 ||
|
|
118
|
-
this.workspaceMetrics.untrackedFiles > 0
|
|
119
|
-
)
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
/**
|
|
123
|
-
* Get workspace summary string
|
|
124
|
-
* @returns {string} Human-readable workspace summary
|
|
125
|
-
*/
|
|
126
|
-
getWorkspaceSummary() {
|
|
127
|
-
const { unstagedFiles, stagedFiles, untrackedFiles } = this.workspaceMetrics
|
|
128
|
-
const parts = []
|
|
129
|
-
|
|
130
|
-
if (stagedFiles > 0) {
|
|
131
|
-
parts.push(`${stagedFiles} staged`)
|
|
132
|
-
}
|
|
133
|
-
if (unstagedFiles > 0) {
|
|
134
|
-
parts.push(`${unstagedFiles} unstaged`)
|
|
135
|
-
}
|
|
136
|
-
if (untrackedFiles > 0) {
|
|
137
|
-
parts.push(`${untrackedFiles} untracked`)
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
return parts.length > 0 ? parts.join(', ') : 'No changes'
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
/**
|
|
144
|
-
* Validate workspace state before operations
|
|
145
|
-
* @returns {Promise<boolean>} True if workspace is valid
|
|
146
|
-
*/
|
|
147
|
-
async validateWorkspace() {
|
|
148
|
-
try {
|
|
149
|
-
// Check if we're in a git repository
|
|
150
|
-
let isGitRepo = false
|
|
151
|
-
try {
|
|
152
|
-
const { execSync } = await import('node:child_process')
|
|
153
|
-
execSync('git rev-parse --is-inside-work-tree', { stdio: 'ignore' })
|
|
154
|
-
isGitRepo = true
|
|
155
|
-
} catch {
|
|
156
|
-
isGitRepo = false
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
if (!isGitRepo) {
|
|
160
|
-
console.error(colors.errorMessage('Not in a git repository'))
|
|
161
|
-
return false
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
const changes = getWorkingDirectoryChanges()
|
|
165
|
-
|
|
166
|
-
// Check if workspace has changes
|
|
167
|
-
if (!this.hasWorkspaceChanges() && changes.length === 0) {
|
|
168
|
-
console.log(colors.infoMessage('No workspace changes detected'))
|
|
169
|
-
return false
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
return true
|
|
173
|
-
} catch (error) {
|
|
174
|
-
console.error(colors.errorMessage(`Workspace validation failed: ${error.message}`))
|
|
175
|
-
return false
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
/**
|
|
180
|
-
* Generate comprehensive workspace changelog
|
|
181
|
-
* @returns {Promise<string>} Comprehensive changelog content
|
|
182
|
-
*/
|
|
183
|
-
async generateComprehensiveWorkspaceChangelog() {
|
|
184
|
-
console.log(colors.processingMessage('📋 Generating comprehensive workspace changelog...'))
|
|
185
|
-
|
|
186
|
-
try {
|
|
187
|
-
const workspaceData = await this.analyzeWorkspaceChanges()
|
|
188
|
-
|
|
189
|
-
if (!workspaceData.analysis) {
|
|
190
|
-
return this.generateBasicWorkspaceChangelog(workspaceData)
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
return await this.generateAIChangelogContentFromChanges(workspaceData.analysis.changes)
|
|
194
|
-
} catch (error) {
|
|
195
|
-
console.error(
|
|
196
|
-
colors.errorMessage(`Failed to generate comprehensive changelog: ${error.message}`)
|
|
197
|
-
)
|
|
198
|
-
throw error
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
/**
|
|
203
|
-
* Generate AI-powered changelog content from changes
|
|
204
|
-
* @param {Array} changes - Array of change objects
|
|
205
|
-
* @returns {Promise<string>} Generated changelog content
|
|
206
|
-
*/
|
|
207
|
-
async generateAIChangelogContentFromChanges(changes) {
|
|
208
|
-
if (!changes || changes.length === 0) {
|
|
209
|
-
return colors.infoMessage('No changes to process for changelog.')
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
try {
|
|
213
|
-
// Use AI analysis service if available
|
|
214
|
-
if (this.aiAnalysisService && this.aiAnalysisService.hasAI) {
|
|
215
|
-
const enhancedChanges = await this.enhanceChangesWithDiff(changes)
|
|
216
|
-
return await this.generateChangelogContent(enhancedChanges)
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
// Fallback to rule-based generation
|
|
220
|
-
return this.generateRuleBasedChangelog(changes)
|
|
221
|
-
} catch (error) {
|
|
222
|
-
console.error(colors.errorMessage(`AI changelog generation failed: ${error.message}`))
|
|
223
|
-
return this.generateRuleBasedChangelog(changes)
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
/**
|
|
228
|
-
* Enhance changes with diff information
|
|
229
|
-
* @param {Array} changes - Array of change objects
|
|
230
|
-
* @returns {Promise<Array>} Enhanced changes with diff data
|
|
231
|
-
*/
|
|
232
|
-
async enhanceChangesWithDiff(changes) {
|
|
233
|
-
const enhancedChanges = []
|
|
234
|
-
|
|
235
|
-
for (const change of changes) {
|
|
236
|
-
try {
|
|
237
|
-
// For workspace changelog service, we don't have detailed diffs
|
|
238
|
-
// Just add basic enhancement
|
|
239
|
-
enhancedChanges.push({
|
|
240
|
-
...change,
|
|
241
|
-
diff: '',
|
|
242
|
-
complexity: this.assessChangeComplexity(''),
|
|
243
|
-
impact: this.assessChangeImpact(change.file, ''),
|
|
244
|
-
})
|
|
245
|
-
} catch (error) {
|
|
246
|
-
console.warn(
|
|
247
|
-
colors.warningMessage(`Failed to enhance change for ${change.file}: ${error.message}`)
|
|
248
|
-
)
|
|
249
|
-
enhancedChanges.push(change)
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
return enhancedChanges
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
/**
|
|
257
|
-
* Generate changelog content from enhanced changes
|
|
258
|
-
* @param {Array} enhancedChanges - Enhanced change objects
|
|
259
|
-
* @returns {Promise<string>} Generated changelog content
|
|
260
|
-
*/
|
|
261
|
-
async generateChangelogContent(enhancedChanges) {
|
|
262
|
-
const sections = {
|
|
263
|
-
features: [],
|
|
264
|
-
fixes: [],
|
|
265
|
-
improvements: [],
|
|
266
|
-
docs: [],
|
|
267
|
-
tests: [],
|
|
268
|
-
chores: [],
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
// Categorize changes
|
|
272
|
-
for (const change of enhancedChanges) {
|
|
273
|
-
const category = this.categorizeChange(change)
|
|
274
|
-
if (sections[category]) {
|
|
275
|
-
sections[category].push(change)
|
|
276
|
-
}
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
// Generate markdown content
|
|
280
|
-
let content = '# Workspace Changes\n\n'
|
|
281
|
-
|
|
282
|
-
for (const [section, changes] of Object.entries(sections)) {
|
|
283
|
-
if (changes.length > 0) {
|
|
284
|
-
content += `## ${this.formatSectionTitle(section)}\n\n`
|
|
285
|
-
|
|
286
|
-
for (const change of changes) {
|
|
287
|
-
content += `- ${this.formatChangeEntry(change)}\n`
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
content += '\n'
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
return content
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
/**
|
|
298
|
-
* Generate commit-style working directory entries
|
|
299
|
-
* @returns {Promise<Array>} Array of commit-style entries
|
|
300
|
-
*/
|
|
301
|
-
async generateCommitStyleWorkingDirectoryEntries() {
|
|
302
|
-
const workspaceData = await this.analyzeWorkspaceChanges()
|
|
303
|
-
const entries = []
|
|
304
|
-
|
|
305
|
-
if (workspaceData.status) {
|
|
306
|
-
// Process staged files
|
|
307
|
-
if (workspaceData.status.staged) {
|
|
308
|
-
for (const file of workspaceData.status.staged) {
|
|
309
|
-
entries.push({
|
|
310
|
-
type: 'staged',
|
|
311
|
-
file,
|
|
312
|
-
message: `Add: ${file}`,
|
|
313
|
-
timestamp: new Date().toISOString(),
|
|
314
|
-
})
|
|
315
|
-
}
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
// Process unstaged files
|
|
319
|
-
if (workspaceData.status.unstaged) {
|
|
320
|
-
for (const file of workspaceData.status.unstaged) {
|
|
321
|
-
entries.push({
|
|
322
|
-
type: 'unstaged',
|
|
323
|
-
file,
|
|
324
|
-
message: `Modify: ${file}`,
|
|
325
|
-
timestamp: new Date().toISOString(),
|
|
326
|
-
})
|
|
327
|
-
}
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
// Process untracked files
|
|
331
|
-
if (workspaceData.status.untracked) {
|
|
332
|
-
for (const file of workspaceData.status.untracked) {
|
|
333
|
-
entries.push({
|
|
334
|
-
type: 'untracked',
|
|
335
|
-
file,
|
|
336
|
-
message: `Create: ${file}`,
|
|
337
|
-
timestamp: new Date().toISOString(),
|
|
338
|
-
})
|
|
339
|
-
}
|
|
340
|
-
}
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
return entries
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
/**
|
|
347
|
-
* Generate workspace changelog
|
|
348
|
-
* @returns {Promise<string>} Workspace changelog content
|
|
349
|
-
*/
|
|
350
|
-
async generateWorkspaceChangelog() {
|
|
351
|
-
console.log(colors.processingMessage('📝 Generating workspace changelog...'))
|
|
352
|
-
|
|
353
|
-
try {
|
|
354
|
-
const entries = await this.generateCommitStyleWorkingDirectoryEntries()
|
|
355
|
-
|
|
356
|
-
if (entries.length === 0) {
|
|
357
|
-
return colors.infoMessage('No workspace changes to include in changelog.')
|
|
358
|
-
}
|
|
359
|
-
|
|
360
|
-
let content = '# Workspace Changes\n\n'
|
|
361
|
-
content += `Generated on: ${new Date().toLocaleString()}\n\n`
|
|
362
|
-
|
|
363
|
-
const groupedEntries = this.groupEntriesByType(entries)
|
|
364
|
-
|
|
365
|
-
for (const [type, typeEntries] of Object.entries(groupedEntries)) {
|
|
366
|
-
if (typeEntries.length > 0) {
|
|
367
|
-
content += `## ${this.formatEntryType(type)} (${typeEntries.length})\n\n`
|
|
368
|
-
|
|
369
|
-
for (const entry of typeEntries) {
|
|
370
|
-
content += `- ${entry.message}\n`
|
|
371
|
-
}
|
|
372
|
-
|
|
373
|
-
content += '\n'
|
|
374
|
-
}
|
|
375
|
-
}
|
|
376
|
-
|
|
377
|
-
return content
|
|
378
|
-
} catch (error) {
|
|
379
|
-
console.error(colors.errorMessage(`Failed to generate workspace changelog: ${error.message}`))
|
|
380
|
-
throw error
|
|
381
|
-
}
|
|
382
|
-
}
|
|
383
|
-
|
|
384
|
-
// Helper methods
|
|
385
|
-
|
|
386
|
-
/**
|
|
387
|
-
* Generate basic workspace changelog without AI
|
|
388
|
-
*/
|
|
389
|
-
generateBasicWorkspaceChangelog(workspaceData) {
|
|
390
|
-
let content = '# Workspace Changes\n\n'
|
|
391
|
-
|
|
392
|
-
if (workspaceData.metrics) {
|
|
393
|
-
content += '## Summary\n\n'
|
|
394
|
-
content += `- Staged files: ${workspaceData.metrics.stagedFiles}\n`
|
|
395
|
-
content += `- Unstaged files: ${workspaceData.metrics.unstagedFiles}\n`
|
|
396
|
-
content += `- Untracked files: ${workspaceData.metrics.untrackedFiles}\n\n`
|
|
397
|
-
}
|
|
398
|
-
|
|
399
|
-
return content
|
|
400
|
-
}
|
|
401
|
-
|
|
402
|
-
/**
|
|
403
|
-
* Generate rule-based changelog fallback
|
|
404
|
-
*/
|
|
405
|
-
generateRuleBasedChangelog(changes) {
|
|
406
|
-
let content = '# Changes Summary\n\n'
|
|
407
|
-
|
|
408
|
-
for (const change of changes) {
|
|
409
|
-
content += `- ${change.type || 'Modified'}: ${change.file}\n`
|
|
410
|
-
}
|
|
411
|
-
|
|
412
|
-
return content
|
|
413
|
-
}
|
|
414
|
-
|
|
415
|
-
/**
|
|
416
|
-
* Assess change complexity
|
|
417
|
-
*/
|
|
418
|
-
assessChangeComplexity(diff) {
|
|
419
|
-
if (!diff) return 'low'
|
|
420
|
-
|
|
421
|
-
const lines = diff.split('\n').length
|
|
422
|
-
if (lines > 100) return 'high'
|
|
423
|
-
if (lines > 20) return 'medium'
|
|
424
|
-
return 'low'
|
|
425
|
-
}
|
|
426
|
-
|
|
427
|
-
/**
|
|
428
|
-
* Assess change impact
|
|
429
|
-
*/
|
|
430
|
-
assessChangeImpact(file, diff) {
|
|
431
|
-
const criticalFiles = ['package.json', 'README.md', 'Dockerfile', '.env']
|
|
432
|
-
const isCritical = criticalFiles.some((critical) => file.includes(critical))
|
|
433
|
-
|
|
434
|
-
if (isCritical) return 'high'
|
|
435
|
-
if (file.includes('test') || file.includes('spec')) return 'low'
|
|
436
|
-
return 'medium'
|
|
437
|
-
}
|
|
438
|
-
|
|
439
|
-
/**
|
|
440
|
-
* Categorize a change
|
|
441
|
-
*/
|
|
442
|
-
categorizeChange(change) {
|
|
443
|
-
const file = change.file.toLowerCase()
|
|
444
|
-
|
|
445
|
-
if (file.includes('test') || file.includes('spec')) return 'tests'
|
|
446
|
-
if (file.includes('readme') || file.includes('doc')) return 'docs'
|
|
447
|
-
if (file.includes('fix') || change.type === 'fix') return 'fixes'
|
|
448
|
-
if (file.includes('feat') || change.type === 'feature') return 'features'
|
|
449
|
-
if (file.includes('config') || file.includes('package')) return 'chores'
|
|
450
|
-
|
|
451
|
-
return 'improvements'
|
|
452
|
-
}
|
|
453
|
-
|
|
454
|
-
/**
|
|
455
|
-
* Format section title
|
|
456
|
-
*/
|
|
457
|
-
formatSectionTitle(section) {
|
|
458
|
-
const titles = {
|
|
459
|
-
features: 'Features',
|
|
460
|
-
fixes: 'Bug Fixes',
|
|
461
|
-
improvements: 'Improvements',
|
|
462
|
-
docs: 'Documentation',
|
|
463
|
-
tests: 'Tests',
|
|
464
|
-
chores: 'Maintenance',
|
|
465
|
-
}
|
|
466
|
-
return titles[section] || section
|
|
467
|
-
}
|
|
468
|
-
|
|
469
|
-
/**
|
|
470
|
-
* Format change entry
|
|
471
|
-
*/
|
|
472
|
-
formatChangeEntry(change) {
|
|
473
|
-
const impact = change.impact ? `[${change.impact}]` : ''
|
|
474
|
-
const complexity = change.complexity ? `{${change.complexity}}` : ''
|
|
475
|
-
return `${change.file} ${impact} ${complexity}`.trim()
|
|
476
|
-
}
|
|
477
|
-
|
|
478
|
-
/**
|
|
479
|
-
* Group entries by type
|
|
480
|
-
*/
|
|
481
|
-
groupEntriesByType(entries) {
|
|
482
|
-
return entries.reduce((groups, entry) => {
|
|
483
|
-
const type = entry.type || 'unknown'
|
|
484
|
-
if (!groups[type]) groups[type] = []
|
|
485
|
-
groups[type].push(entry)
|
|
486
|
-
return groups
|
|
487
|
-
}, {})
|
|
488
|
-
}
|
|
489
|
-
|
|
490
|
-
/**
|
|
491
|
-
* Format entry type for display
|
|
492
|
-
*/
|
|
493
|
-
formatEntryType(type) {
|
|
494
|
-
const types = {
|
|
495
|
-
staged: 'Staged Changes',
|
|
496
|
-
unstaged: 'Unstaged Changes',
|
|
497
|
-
untracked: 'New Files',
|
|
498
|
-
}
|
|
499
|
-
return types[type] || type
|
|
500
|
-
}
|
|
501
|
-
|
|
502
|
-
/**
|
|
503
|
-
* Initialize workspace for analysis
|
|
504
|
-
* @returns {Promise<boolean>} True if initialization successful
|
|
505
|
-
*/
|
|
506
|
-
async initializeWorkspace() {
|
|
507
|
-
try {
|
|
508
|
-
console.log(colors.processingMessage('🔧 Initializing workspace...'))
|
|
509
|
-
|
|
510
|
-
// Reset metrics
|
|
511
|
-
this.cleanup()
|
|
512
|
-
|
|
513
|
-
// Validate git repository
|
|
514
|
-
const isValid = await this.validateWorkspace()
|
|
515
|
-
if (!isValid) {
|
|
516
|
-
return false
|
|
517
|
-
}
|
|
518
|
-
|
|
519
|
-
// Perform initial analysis
|
|
520
|
-
await this.analyzeWorkspaceChanges()
|
|
521
|
-
|
|
522
|
-
console.log(colors.successMessage('✅ Workspace initialized successfully'))
|
|
523
|
-
return true
|
|
524
|
-
} catch (error) {
|
|
525
|
-
console.error(colors.errorMessage(`Failed to initialize workspace: ${error.message}`))
|
|
526
|
-
return false
|
|
527
|
-
}
|
|
528
|
-
}
|
|
529
|
-
|
|
530
|
-
/**
|
|
531
|
-
* Validate workspace structure
|
|
532
|
-
* @returns {boolean} True if workspace structure is valid
|
|
533
|
-
*/
|
|
534
|
-
validateWorkspaceStructure() {
|
|
535
|
-
try {
|
|
536
|
-
// Check if we have the required services
|
|
537
|
-
if (!this.gitService) {
|
|
538
|
-
console.error(colors.errorMessage('Git service not available'))
|
|
539
|
-
return false
|
|
540
|
-
}
|
|
541
|
-
|
|
542
|
-
// Check if workspace has any changes to analyze
|
|
543
|
-
if (!this.hasWorkspaceChanges()) {
|
|
544
|
-
console.log(colors.infoMessage('No workspace changes detected'))
|
|
545
|
-
return true // Still valid, just nothing to do
|
|
546
|
-
}
|
|
547
|
-
|
|
548
|
-
return true
|
|
549
|
-
} catch (error) {
|
|
550
|
-
console.error(colors.errorMessage(`Workspace structure validation failed: ${error.message}`))
|
|
551
|
-
return false
|
|
552
|
-
}
|
|
553
|
-
}
|
|
554
|
-
|
|
555
|
-
/**
|
|
556
|
-
* Clean up workspace analysis resources
|
|
557
|
-
*/
|
|
558
|
-
cleanup() {
|
|
559
|
-
this.workspaceMetrics = {
|
|
560
|
-
unstagedFiles: 0,
|
|
561
|
-
stagedFiles: 0,
|
|
562
|
-
untrackedFiles: 0,
|
|
563
|
-
modifiedLines: 0,
|
|
564
|
-
}
|
|
565
|
-
}
|
|
566
|
-
}
|