@entro314labs/ai-changelog-generator 3.0.5 → 3.1.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/CHANGELOG.md CHANGED
@@ -5,6 +5,98 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [3.1.1] - 2025-08-01 ([480d3bc...a55fbc9](https://github.com/entro314-labs/AI-changelog-generator/compare/480d3bc9ac50fb983ddcf856aa99f9cc05cfc601...a55fbc98c36bd95d44d1582ed290b432e696058a))
9
+
10
+ ### šŸ“‹ Release Summary
11
+ Release 3.1.1 includes 10 commits (3 chore, 2 feature, 2 fix, 2 refactor, 1 docs). Complexity: low. Affected areas: configuration, documentation, source, other, assets.
12
+
13
+ **Business Impact**: minor
14
+ **Complexity**: low
15
+
16
+ ## Changes
17
+
18
+ ### šŸ”§ Maintenance
19
+
20
+ - **Update package.json**: The package version was incremented from 3.0.4 to 3.0.5 in package.json. No functional or dependency changes were made. ([641ad94](https://github.com/entro314-labs/AI-changelog-generator/commit/641ad94a5907d587f4427d1bfab195f7590a20a6))
21
+ - **Update package.json**: The version field in package.json was incremented from 3.0.3 to 3.0.4. No functionality, dependencies, or APIs were changed. ([787425e](https://github.com/entro314-labs/AI-changelog-generator/commit/787425e6f9b8524a3a2ee894ee201fcf29fc2e44))
22
+
23
+ ### šŸ“š Documentation
24
+
25
+ - **minor updates**: A comprehensive new setup guide was added, while several older, more detailed documentation files were removed for clarity and maintainability. Minor updates were made to documentation references and copyright information. ([28c0949](https://github.com/entro314-labs/AI-changelog-generator/commit/28c0949bcf455be78efae9162a4463bfc54afe3e))
26
+
27
+ ### šŸ› Bug Fixes
28
+
29
+ - **fix: add publishConfig for public access**: Added a publishConfig section to package.json to specify public access for npm publishing. No application logic or user-facing functionality was changed. ([0f78591](https://github.com/entro314-labs/AI-changelog-generator/commit/0f7859165c80f29383afe6d02f88999664c29459))
30
+ - **fix: remove prepublishOnly hook with missing test-runner**: The 'prepublishOnly' npm script, which referenced a non-existent test runner, was removed from package.json. This prevents publishing errors caused by the missing script. ([0e7d691](https://github.com/entro314-labs/AI-changelog-generator/commit/0e7d691da1da409e57cabf77baf55f92b2d47d41))
31
+ - **fix: remove missing validate:mcp script from prepublishOnly**: Removed the call to the non-existent 'validate:mcp' script from the 'prepublishOnly' lifecycle step in package.json. Only 'test:comprehensive' now runs before publishing. ([215c644](https://github.com/entro314-labs/AI-changelog-generator/commit/215c6440005607ed56684e8d7906be5fe252e6fc))
32
+
33
+ ### ā™»ļø Refactoring
34
+
35
+ - **minor naming changes**: Internal code references to utility functions were updated to use a new file naming convention, changing imports from 'consolidated-utils.js' to 'utils.js' across multiple modules. No new features, APIs, or behavioral changes were introduced. ([3b99ef2](https://github.com/entro314-labs/AI-changelog-generator/commit/3b99ef20c6c3d39c5c1d7c0ea0ed8a84da07de34))
36
+ - **minor naming updates**: This update removes sample DXT extension files and documentation, and restructures the MCP server entry point for clarity and maintainability. Internal naming and initialization logic were adjusted, but no APIs or user commands were added or removed. ([480d3bc](https://github.com/entro314-labs/AI-changelog-generator/commit/480d3bc9ac50fb983ddcf856aa99f9cc05cfc601))
37
+
38
+ ### šŸ”§ Working Directory Changes
39
+
40
+ - (feature) Expanded color constants in colors.js - Added new color entries including 'dracula', 'draculaDark', 'draculaLight', 'draculaYellow', 'draculaCyan', 'draculaOrange', 'draculaPink', 'draculaPurple', 'draculaRed', 'draculaGreen', and 'draculaBackground' to the exported COLORS object.
41
+
42
+ - (docs) Added changelog for version 3.1.0 - Created CHANGELOG-3.1.0.md with 50 lines detailing changes for version 3.1.0 dated 2025-08-01.
43
+
44
+ - (other) Added demo tape and video files - Created demo-basic.tape, demo-features.tape, demo-interactive.tape, demo-quick-real.tape, demo-quick.tape, demo-simple.tape, and demo.tape with various demo scripts; added demo.mp4 and demo-interactive.mp4 video files.
45
+
46
+ - (assets) Added demo GIF assets - Created demo-interactive-optimized.gif and demo-quick-real.gif with image data; added empty demo-interactive.gif, demo-optimized.gif, and demo-simple.gif files.
47
+
48
+ ---
49
+
50
+ *Generated using [ai-changelog-generator](https://github.com/entro314-labs/AI-changelog-generator) - AI-powered changelog generation for Git repositories*
51
+
52
+ ## [3.1.0] - 2025-08-01 ([480d3bc...a55fbc9](https://github.com/entro314-labs/AI-changelog-generator/compare/480d3bc9ac50fb983ddcf856aa99f9cc05cfc601...a55fbc98c36bd95d44d1582ed290b432e696058a))
53
+
54
+ ### šŸ“‹ Release Summary
55
+ Release 3.1.0 includes 10 commits (3 chore, 2 feature, 2 fix, 2 refactor, 1 docs). Complexity: low. Affected areas: configuration, documentation, source, other, assets.
56
+
57
+ **Business Impact**: minor
58
+ **Complexity**: low
59
+
60
+ ## Changes
61
+
62
+ ### šŸ”§ Maintenance
63
+
64
+ - **Update package.json**: The package.json file version was updated from 3.0.4 to 3.0.5. No functionality, dependencies, or configuration were changed. ([641ad94](https://github.com/entro314-labs/AI-changelog-generator/commit/641ad94a5907d587f4427d1bfab195f7590a20a6))
65
+ - **Update package.json**: The package version was updated from 3.0.3 to 3.0.4 in package.json. No code, features, or dependencies were changed. ([787425e](https://github.com/entro314-labs/AI-changelog-generator/commit/787425e6f9b8524a3a2ee894ee201fcf29fc2e44))
66
+
67
+ ### šŸ“š Documentation
68
+
69
+ - **minor updates**: A new comprehensive 'AI Provider Setup Guide' was added, consolidating and simplifying provider configuration instructions; several outdated or redundant documentation files were removed, and the .gitignore was updated to exclude these files. No application code or user-facing features were changed. ([28c0949](https://github.com/entro314-labs/AI-changelog-generator/commit/28c0949bcf455be78efae9162a4463bfc54afe3e))
70
+
71
+ ### šŸ› Bug Fixes
72
+
73
+ - **fix: add publishConfig for public access**: Added a publishConfig section with 'access: public' to package.json, ensuring the package is published with public visibility. No application code or runtime behavior was changed. ([0f78591](https://github.com/entro314-labs/AI-changelog-generator/commit/0f7859165c80f29383afe6d02f88999664c29459))
74
+ - **fix: remove prepublishOnly hook with missing test-runner**: The 'prepublishOnly' npm script, which referenced a non-existent 'test:comprehensive' command, was removed from package.json. This prevents npm publish operations from being blocked by missing scripts. ([0e7d691](https://github.com/entro314-labs/AI-changelog-generator/commit/0e7d691da1da409e57cabf77baf55f92b2d47d41))
75
+ - **fix: remove missing validate:mcp script from prepublishOnly**: The prepublishOnly script no longer tries to run the removed validate:mcp command, which previously caused errors if the script was absent. Only the comprehensive test suite is now run before publishing. ([215c644](https://github.com/entro314-labs/AI-changelog-generator/commit/215c6440005607ed56684e8d7906be5fe252e6fc))
76
+
77
+ ### ā™»ļø Refactoring
78
+
79
+ - **minor naming changes**: The update consolidates utility imports by renaming and redirecting them from 'consolidated-utils.js' to 'utils.js' across core modules and provider integrations. No APIs, commands, or outputs were changed; only internal code references were updated for consistency. ([3b99ef2](https://github.com/entro314-labs/AI-changelog-generator/commit/3b99ef20c6c3d39c5c1d7c0ea0ed8a84da07de34))
80
+ - šŸ”„ **minor naming updates**: This update removes all sample DXT extension packages, documentation, and related files, and restructures the MCP server entry point and supporting utilities for improved clarity and maintainability. No new tools or APIs were introduced, and no user-facing commands or behaviors were modified. ([480d3bc](https://github.com/entro314-labs/AI-changelog-generator/commit/480d3bc9ac50fb983ddcf856aa99f9cc05cfc601))
81
+
82
+ ### šŸ”§ Working Directory Changes
83
+
84
+ - (feature) Added demo-optimized.gif asset - Created new empty file demo-optimized.gif in assets.
85
+
86
+ - (feature) Added demo-simple.gif asset - Created new empty file demo-simple.gif in assets.
87
+
88
+ - (feature) Added demo-quick.tape script - Created new file demo-quick.tape with 70 lines, including commands for outputting demo-quick.gif, setting font size, width, height, theme, typing speed, and various typing and enter actions.
89
+
90
+ - (feature) Added demo-simple.tape script - Created new file demo-simple.tape with 24 lines, including commands for outputting demo-simple.gif, setting font size, width, height, theme, typing speed, and typing a demo title.
91
+
92
+ - (feature) Added demo.mp4 media file - Created new file demo.mp4 with 3243 lines of binary content.
93
+
94
+ - (feature) Added demo.tape script - Created new file demo.tape with 129 lines, including documentation comments and commands for outputting GIF and MP4 files, setting font size, width, height, theme, typing speed, and various typing and enter actions.
95
+
96
+ ---
97
+
98
+ *Generated using [ai-changelog-generator](https://github.com/entro314-labs/AI-changelog-generator) - AI-powered changelog generation for Git repositories*
99
+
8
100
  ## [3.0.3]
9
101
 
10
102
  ### šŸ”§ **Maintenance & Bug Fixes**
package/README.md CHANGED
@@ -148,6 +148,27 @@ ai-changelog --help
148
148
 
149
149
  That's it! Your AI-powered changelog is ready to generate.
150
150
 
151
+ ## Demo
152
+
153
+ ### Interactive Mode
154
+ See the tool in action with our interactive mode demo:
155
+
156
+ ![Interactive Demo](docs/media/demo-interactive-optimized.gif)
157
+
158
+ *Interactive mode with guided setup and provider selection*
159
+
160
+ ### Quick Generation
161
+ Watch how fast you can generate professional changelogs:
162
+
163
+ ![Quick Demo](docs/media/demo-quick-real.gif)
164
+
165
+ *Generate changelogs from recent commits in seconds*
166
+
167
+ ### Video Walkthrough
168
+ For a complete walkthrough of features and capabilities:
169
+
170
+ [šŸ“ŗ Watch Full Demo Video](docs/media/demo-interactive.mp4)
171
+
151
172
  ## How It Works
152
173
 
153
174
  1. **Code Analysis**: Analyzes actual git diffs and file changes using advanced AI models
@@ -326,6 +347,7 @@ ai-changelog health --detailed
326
347
  - **[Configuration Reference](./docs/configuration.md)** - All YAML and environment options
327
348
  - **[MCP Integration](./docs/mcp-integration.md)** - Claude Desktop and MCP server setup
328
349
  - **[API Reference](./docs/api-reference.md)** - All commands, options, and programmatic usage
350
+ - **[Demo Media](./docs/media/)** - Interactive demos, GIFs, and video walkthroughs
329
351
 
330
352
  ## Contributing
331
353
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@entro314labs/ai-changelog-generator",
3
3
  "displayName": "AI Changelog Generator",
4
- "version": "3.0.5",
4
+ "version": "3.1.1",
5
5
  "type": "module",
6
6
  "description": "AI-powered changelog generator with MCP server support - works with most providers, online and local models",
7
7
  "main": "src/ai-changelog-generator.js",
@@ -21,28 +21,28 @@
21
21
  "CHANGELOG.md"
22
22
  ],
23
23
  "dependencies": {
24
- "@anthropic-ai/sdk": "^0.57.0",
25
- "@aws-sdk/client-bedrock-runtime": "^3.857.0",
26
- "@azure/identity": "^4.10.2",
24
+ "@anthropic-ai/sdk": "^0.58.0",
25
+ "@aws-sdk/client-bedrock-runtime": "^3.861.0",
26
+ "@azure/identity": "^4.11.1",
27
27
  "@clack/prompts": "^0.11.0",
28
28
  "@google/genai": "^1.12.0",
29
29
  "@google/generative-ai": "^0.24.1",
30
30
  "@huggingface/hub": "^2.4.0",
31
31
  "@huggingface/inference": "^4.6.1",
32
32
  "@lmstudio/sdk": "^1.4.0",
33
- "@modelcontextprotocol/sdk": "^1.17.0",
34
- "@modelcontextprotocol/server-filesystem": "2025.7.1",
35
- "chalk": "^5.4.1",
33
+ "@modelcontextprotocol/sdk": "^1.17.1",
34
+ "@modelcontextprotocol/server-filesystem": "2025.7.29",
35
+ "chalk": "^5.5.0",
36
36
  "dotenv": "^17.2.1",
37
- "google-auth-library": "^10.2.0",
37
+ "google-auth-library": "^10.2.1",
38
38
  "js-yaml": "^4.1.0",
39
39
  "ollama": "^0.5.16",
40
- "openai": "^5.11.0",
40
+ "openai": "^5.12.0",
41
41
  "yargs": "^18.0.0"
42
42
  },
43
43
  "devDependencies": {
44
44
  "@anthropic-ai/dxt": "^0.2.6",
45
- "@types/node": "22.15.30"
45
+ "@types/node": "22.17.1"
46
46
  },
47
47
  "keywords": [
48
48
  "changelog",
@@ -4,6 +4,8 @@ import { ChangelogService } from '../../domains/changelog/changelog.service.js';
4
4
  import { AnalysisEngine } from '../../domains/analysis/analysis.engine.js';
5
5
  import { ProviderManagerService } from '../../infrastructure/providers/provider-manager.service.js';
6
6
  import { InteractiveWorkflowService } from '../../infrastructure/interactive/interactive-workflow.service.js';
7
+ import { InteractiveStagingService } from '../../infrastructure/interactive/interactive-staging.service.js';
8
+ import { CommitMessageValidationService } from '../../infrastructure/validation/commit-message-validation.service.js';
7
9
  import colors from '../../shared/constants/colors.js';
8
10
 
9
11
  export class ChangelogOrchestrator {
@@ -54,6 +56,8 @@ export class ChangelogOrchestrator {
54
56
  this.analysisEngine = new AnalysisEngine(this.gitService, this.aiAnalysisService);
55
57
  this.changelogService = new ChangelogService(this.gitService, this.aiAnalysisService, this.analysisEngine, this.configManager);
56
58
  this.interactiveService = new InteractiveWorkflowService(this.gitService, this.aiAnalysisService, this.changelogService);
59
+ this.stagingService = new InteractiveStagingService(this.gitManager);
60
+ this.validationService = new CommitMessageValidationService(this.configManager);
57
61
 
58
62
  // Only log if not in MCP server mode
59
63
  if (!process.env.MCP_SERVER_MODE) {
@@ -727,4 +731,469 @@ export class ChangelogOrchestrator {
727
731
  this.aiAnalysisService.resetMetrics();
728
732
  }
729
733
  }
734
+
735
+ // Interactive commit workflow
736
+ async executeCommitWorkflow(options = {}) {
737
+ await this.ensureInitialized();
738
+
739
+ console.log(colors.header('šŸš€ Interactive Commit Workflow'));
740
+
741
+ try {
742
+ // Step 1: Show current git status
743
+ const statusResult = await this.stagingService.showGitStatus();
744
+
745
+ // Check if we have any changes at all
746
+ const totalChanges = statusResult.staged.length + statusResult.unstaged.length + statusResult.untracked.length;
747
+ if (totalChanges === 0) {
748
+ console.log(colors.infoMessage('✨ Working directory clean - no changes to commit.'));
749
+ return { success: false, message: 'No changes to commit' };
750
+ }
751
+
752
+ // Step 2: Handle staging based on options
753
+ let stagedFiles = [];
754
+
755
+ if (options.stageAll) {
756
+ // Auto-stage all changes
757
+ console.log(colors.processingMessage('šŸ“¦ Staging all changes...'));
758
+ await this.stagingService.stageAllChanges();
759
+ stagedFiles = [...statusResult.unstaged, ...statusResult.untracked];
760
+ } else if (options.interactive && (statusResult.unstaged.length > 0 || statusResult.untracked.length > 0)) {
761
+ // Interactive staging
762
+ console.log(colors.infoMessage('\nšŸŽÆ Interactive staging mode'));
763
+ stagedFiles = await this.stagingService.selectFilesToStage();
764
+
765
+ if (stagedFiles.length === 0 && statusResult.staged.length === 0) {
766
+ console.log(colors.warningMessage('No files staged for commit.'));
767
+ return { success: false, message: 'No files staged' };
768
+ }
769
+ }
770
+
771
+ // Step 3: Verify we have staged changes
772
+ if (!this.stagingService.hasStagedChanges()) {
773
+ console.log(colors.warningMessage('No staged changes found for commit.'));
774
+
775
+ if (statusResult.unstaged.length > 0 || statusResult.untracked.length > 0) {
776
+ console.log(colors.infoMessage('šŸ’” Use --all flag to stage all changes, or run interactively to select files.'));
777
+ }
778
+
779
+ return { success: false, message: 'No staged changes' };
780
+ }
781
+
782
+ // Step 4: Get final staged changes for analysis
783
+ const finalStatus = this.stagingService.getDetailedStatus();
784
+ console.log(colors.successMessage(`\nāœ… Ready to commit ${finalStatus.staged.length} staged file(s)`));
785
+
786
+ // Step 5: Branch Intelligence Analysis
787
+ const { analyzeBranchIntelligence, getSuggestedCommitType, generateCommitContextFromBranch } = await import('../../shared/utils/utils.js');
788
+
789
+ const branchAnalysis = analyzeBranchIntelligence();
790
+ const suggestedType = getSuggestedCommitType(branchAnalysis, finalStatus.staged);
791
+ const branchContext = generateCommitContextFromBranch(branchAnalysis, finalStatus.staged);
792
+
793
+ // Display branch intelligence findings
794
+ if (branchAnalysis.confidence > 20) {
795
+ console.log(colors.infoMessage('\n🧠 Branch Intelligence:'));
796
+ console.log(colors.secondary(` Branch: ${branchAnalysis.branch}`));
797
+
798
+ if (branchAnalysis.type) {
799
+ console.log(colors.success(` šŸ·ļø Detected type: ${branchAnalysis.type} (${branchAnalysis.confidence}% confidence)`));
800
+ }
801
+
802
+ if (branchAnalysis.ticket) {
803
+ console.log(colors.highlight(` šŸŽ« Related ticket: ${branchAnalysis.ticket}`));
804
+ }
805
+
806
+ if (branchAnalysis.description) {
807
+ console.log(colors.dim(` šŸ“ Description: ${branchAnalysis.description}`));
808
+ }
809
+
810
+ console.log(colors.dim(` šŸ” Patterns: ${branchAnalysis.patterns.join(', ')}`));
811
+ }
812
+
813
+ // Display suggested commit type
814
+ console.log(colors.infoMessage(`\nšŸ’” Suggested commit type: ${colors.highlight(suggestedType.type)} (from ${suggestedType.source}, ${suggestedType.confidence}% confidence)`));
815
+
816
+ // Step 6: Generate enhanced commit message
817
+ let commitMessage;
818
+
819
+ if (options.customMessage) {
820
+ commitMessage = options.customMessage;
821
+ } else {
822
+ // Generate AI-enhanced commit message with branch context
823
+ commitMessage = this.generateBranchAwareCommitMessage(branchAnalysis, suggestedType, finalStatus.staged);
824
+ }
825
+
826
+ // Step 7: Validate commit message
827
+ console.log(colors.processingMessage('\nšŸ” Validating commit message...'));
828
+
829
+ const validationContext = {
830
+ branchAnalysis,
831
+ stagedFiles: finalStatus.staged,
832
+ suggestedType
833
+ };
834
+
835
+ const validationResult = await this.validationService.validateCommitMessage(commitMessage, validationContext);
836
+
837
+ // Display validation results
838
+ const isValid = this.validationService.displayValidationResults(validationResult);
839
+
840
+ // Step 8: Interactive improvement if needed
841
+ if (!isValid || validationResult.warnings.length > 0) {
842
+ const { confirm } = await import('@clack/prompts');
843
+
844
+ const shouldImprove = await confirm({
845
+ message: 'Would you like to improve the commit message?',
846
+ initialValue: !isValid
847
+ });
848
+
849
+ if (shouldImprove) {
850
+ commitMessage = await this.handleCommitMessageImprovement(commitMessage, validationResult, validationContext);
851
+ }
852
+ }
853
+
854
+ if (options.dryRun) {
855
+ console.log(colors.infoMessage('\nšŸ“‹ Dry-run mode - showing what would be committed:'));
856
+ console.log(colors.highlight(`Commit message:\n${commitMessage}`));
857
+ return {
858
+ success: true,
859
+ commitMessage,
860
+ stagedFiles: finalStatus.staged.length,
861
+ dryRun: true
862
+ };
863
+ }
864
+
865
+ // Step 6: Development phase notice
866
+ console.log(colors.warningMessage('\nāš ļø Commit execution is in development phase.'));
867
+ console.log(colors.infoMessage('Current capabilities:'));
868
+ console.log(colors.success(' • Git status analysis āœ…'));
869
+ console.log(colors.success(' • Interactive staging āœ…'));
870
+ console.log(colors.dim(' • AI commit message generation (coming soon) ā³'));
871
+ console.log(colors.dim(' • Git commit execution (coming soon) ā³'));
872
+
873
+ console.log(colors.infoMessage('\nšŸ’” Files are staged and ready for commit!'));
874
+ console.log(colors.infoMessage('šŸ’” Use "git commit" manually or wait for the next phase.'));
875
+
876
+ return {
877
+ success: true,
878
+ commitMessage,
879
+ stagedFiles: finalStatus.staged.length,
880
+ phase: 'staging-complete'
881
+ };
882
+
883
+ } catch (error) {
884
+ console.error(colors.errorMessage(`Commit workflow error: ${error.message}`));
885
+ throw error;
886
+ }
887
+ }
888
+
889
+ /**
890
+ * Generate branch-aware commit message using AI and branch intelligence
891
+ */
892
+ generateBranchAwareCommitMessage(branchAnalysis, suggestedType, stagedFiles) {
893
+ const type = suggestedType.type;
894
+
895
+ // Build description based on branch intelligence
896
+ let description = 'implement changes';
897
+
898
+ if (branchAnalysis.description && branchAnalysis.confidence > 40) {
899
+ description = branchAnalysis.description;
900
+ } else {
901
+ // Generate description from file changes
902
+ const fileTypes = new Set();
903
+ stagedFiles.forEach(file => {
904
+ const path = file.path;
905
+ if (path.includes('service')) fileTypes.add('services');
906
+ if (path.includes('component')) fileTypes.add('components');
907
+ if (path.includes('utils')) fileTypes.add('utilities');
908
+ if (path.includes('config')) fileTypes.add('configuration');
909
+ if (path.includes('test')) fileTypes.add('tests');
910
+ if (path.includes('doc')) fileTypes.add('documentation');
911
+ });
912
+
913
+ if (fileTypes.size > 0) {
914
+ description = `update ${Array.from(fileTypes).join(', ')}`;
915
+ }
916
+ }
917
+
918
+ // Build commit message
919
+ let commitMessage = `${type}: ${description}`;
920
+
921
+ // Add body with details
922
+ const bodyLines = [];
923
+
924
+ if (branchAnalysis.ticket) {
925
+ bodyLines.push(`Related to: ${branchAnalysis.ticket}`);
926
+ }
927
+
928
+ // Add file summary
929
+ const addedFiles = stagedFiles.filter(f => f.status === 'A').length;
930
+ const modifiedFiles = stagedFiles.filter(f => f.status === 'M').length;
931
+ const deletedFiles = stagedFiles.filter(f => f.status === 'D').length;
932
+
933
+ const changes = [];
934
+ if (addedFiles > 0) changes.push(`${addedFiles} added`);
935
+ if (modifiedFiles > 0) changes.push(`${modifiedFiles} modified`);
936
+ if (deletedFiles > 0) changes.push(`${deletedFiles} deleted`);
937
+
938
+ if (changes.length > 0) {
939
+ bodyLines.push(`Files: ${changes.join(', ')}`);
940
+ }
941
+
942
+ // Add branch context
943
+ if (branchAnalysis.confidence > 60) {
944
+ bodyLines.push(`Branch: ${branchAnalysis.branch} (${branchAnalysis.confidence}% confidence)`);
945
+ }
946
+
947
+ if (bodyLines.length > 0) {
948
+ commitMessage += '\n\n' + bodyLines.join('\n');
949
+ }
950
+
951
+ return commitMessage;
952
+ }
953
+
954
+ /**
955
+ * Handle interactive commit message improvement
956
+ */
957
+ async handleCommitMessageImprovement(originalMessage, validationResult, context) {
958
+ const { select, text, confirm } = await import('@clack/prompts');
959
+
960
+ console.log(colors.infoMessage('\nšŸ”§ Commit Message Improvement'));
961
+
962
+ // Try automatic improvement first
963
+ const improvementResult = await this.validationService.improveCommitMessage(originalMessage, context);
964
+
965
+ const options = [
966
+ {
967
+ value: 'auto',
968
+ label: 'šŸ¤– Use automatically improved version',
969
+ hint: improvementResult.improved ? 'AI-suggested improvements applied' : 'Minor fixes applied'
970
+ },
971
+ {
972
+ value: 'manual',
973
+ label: 'āœļø Edit manually',
974
+ hint: 'Customize the commit message yourself'
975
+ }
976
+ ];
977
+
978
+ // Add AI suggestions if available
979
+ if (this.aiAnalysisService.hasAI) {
980
+ options.unshift({
981
+ value: 'ai',
982
+ label: '🧠 Generate AI suggestions',
983
+ hint: 'Get AI-powered commit message alternatives'
984
+ });
985
+ }
986
+
987
+ const choice = await select({
988
+ message: 'How would you like to improve the commit message?',
989
+ options
990
+ });
991
+
992
+ switch (choice) {
993
+ case 'ai':
994
+ return await this.generateAICommitSuggestions(originalMessage, context, validationResult);
995
+
996
+ case 'auto':
997
+ console.log(colors.successMessage(`\nāœ… Using improved message:`));
998
+ console.log(colors.highlight(improvementResult.message));
999
+ return improvementResult.message;
1000
+
1001
+ case 'manual':
1002
+ return await this.handleManualCommitEdit(originalMessage, validationResult);
1003
+
1004
+ default:
1005
+ return originalMessage;
1006
+ }
1007
+ }
1008
+
1009
+ /**
1010
+ * Generate AI-powered commit message suggestions
1011
+ */
1012
+ async generateAICommitSuggestions(originalMessage, context, validationResult) {
1013
+ const { select } = await import('@clack/prompts');
1014
+
1015
+ console.log(colors.processingMessage('šŸ¤– Generating AI suggestions...'));
1016
+
1017
+ try {
1018
+ // Build comprehensive context for AI
1019
+ const branchInfo = context.branchAnalysis?.confidence > 30
1020
+ ? `Branch: ${context.branchAnalysis.branch} (${context.branchAnalysis.type || 'unknown'} type)`
1021
+ : '';
1022
+
1023
+ const fileChanges = context.stagedFiles.map(f => `${f.status} ${f.path}`).join('\n');
1024
+
1025
+ const validationIssues = [
1026
+ ...validationResult.errors,
1027
+ ...validationResult.warnings
1028
+ ].join('\n');
1029
+
1030
+ const prompt = `Improve this commit message based on the validation feedback and context:
1031
+
1032
+ Original message: "${originalMessage}"
1033
+
1034
+ Validation issues:
1035
+ ${validationIssues}
1036
+
1037
+ File changes:
1038
+ ${fileChanges}
1039
+
1040
+ ${branchInfo}
1041
+
1042
+ Requirements:
1043
+ - Follow conventional commit format
1044
+ - Address all validation issues
1045
+ - Keep subject under 72 characters
1046
+ - Use imperative mood
1047
+ - Be specific and descriptive
1048
+
1049
+ Provide 3 improved alternatives.`;
1050
+
1051
+ const response = await this.aiAnalysisService.aiProvider.generateCompletion([{
1052
+ role: 'user',
1053
+ content: prompt
1054
+ }], { max_tokens: 300 });
1055
+
1056
+ const suggestions = this.parseAICommitSuggestions(response.content);
1057
+
1058
+ if (suggestions.length === 0) {
1059
+ console.log(colors.warningMessage('No AI suggestions generated, falling back to manual edit.'));
1060
+ return await this.handleManualCommitEdit(originalMessage, validationResult);
1061
+ }
1062
+
1063
+ // Present suggestions to user
1064
+ const choices = suggestions.map((suggestion, index) => ({
1065
+ value: suggestion,
1066
+ label: `${index + 1}. ${suggestion.split('\n')[0]}`, // First line only
1067
+ hint: suggestion.includes('\n') ? 'Has body content' : 'Subject only'
1068
+ }));
1069
+
1070
+ choices.push({
1071
+ value: 'MANUAL',
1072
+ label: 'āœļø Edit manually instead',
1073
+ hint: 'Write your own commit message'
1074
+ });
1075
+
1076
+ const selectedMessage = await select({
1077
+ message: 'Choose an AI-generated commit message:',
1078
+ options: choices
1079
+ });
1080
+
1081
+ if (selectedMessage === 'MANUAL') {
1082
+ return await this.handleManualCommitEdit(originalMessage, validationResult);
1083
+ }
1084
+
1085
+ console.log(colors.successMessage('\nāœ… Selected AI suggestion:'));
1086
+ console.log(colors.highlight(selectedMessage));
1087
+ return selectedMessage;
1088
+
1089
+ } catch (error) {
1090
+ console.error(colors.errorMessage(`AI suggestion failed: ${error.message}`));
1091
+ return await this.handleManualCommitEdit(originalMessage, validationResult);
1092
+ }
1093
+ }
1094
+
1095
+ /**
1096
+ * Handle manual commit message editing
1097
+ */
1098
+ async handleManualCommitEdit(originalMessage, validationResult) {
1099
+ const { text, confirm } = await import('@clack/prompts');
1100
+
1101
+ console.log(colors.infoMessage('\nāœļø Manual Edit Mode'));
1102
+ console.log(colors.dim('Validation issues to address:'));
1103
+
1104
+ validationResult.errors.forEach(error => {
1105
+ console.log(colors.error(` • ${error}`));
1106
+ });
1107
+
1108
+ validationResult.warnings.forEach(warning => {
1109
+ console.log(colors.warning(` • ${warning}`));
1110
+ });
1111
+
1112
+ if (validationResult.suggestions.length > 0) {
1113
+ console.log(colors.dim('\nSuggestions:'));
1114
+ validationResult.suggestions.forEach(suggestion => {
1115
+ console.log(colors.dim(` • ${suggestion}`));
1116
+ });
1117
+ }
1118
+
1119
+ let improvedMessage;
1120
+ let isValid = false;
1121
+ let attempts = 0;
1122
+ const maxAttempts = 3;
1123
+
1124
+ while (!isValid && attempts < maxAttempts) {
1125
+ improvedMessage = await text({
1126
+ message: 'Enter improved commit message:',
1127
+ placeholder: originalMessage,
1128
+ defaultValue: attempts === 0 ? originalMessage : undefined,
1129
+ validate: (input) => {
1130
+ if (!input || input.trim().length === 0) {
1131
+ return 'Commit message cannot be empty';
1132
+ }
1133
+ }
1134
+ });
1135
+
1136
+ // Validate the improved message
1137
+ const newValidation = await this.validationService.validateCommitMessage(improvedMessage, {
1138
+ branchAnalysis: validationResult.parsed?.branchAnalysis
1139
+ });
1140
+
1141
+ if (newValidation.valid) {
1142
+ isValid = true;
1143
+ console.log(colors.successMessage('āœ… Validation passed!'));
1144
+ } else {
1145
+ attempts++;
1146
+ console.log(colors.warningMessage(`\nāš ļø Validation failed (attempt ${attempts}/${maxAttempts}):`));
1147
+ this.validationService.displayValidationResults(newValidation);
1148
+
1149
+ if (attempts < maxAttempts) {
1150
+ const tryAgain = await confirm({
1151
+ message: 'Try again with improvements?',
1152
+ initialValue: true
1153
+ });
1154
+
1155
+ if (!tryAgain) {
1156
+ break;
1157
+ }
1158
+ }
1159
+ }
1160
+ }
1161
+
1162
+ return improvedMessage || originalMessage;
1163
+ }
1164
+
1165
+ /**
1166
+ * Parse AI-generated commit suggestions
1167
+ */
1168
+ parseAICommitSuggestions(content) {
1169
+ const suggestions = [];
1170
+ const lines = content.split('\n').filter(line => line.trim());
1171
+
1172
+ let currentSuggestion = '';
1173
+ for (const line of lines) {
1174
+ const trimmed = line.trim();
1175
+
1176
+ // Check if it's a new suggestion (starts with number, bullet, or looks like commit format)
1177
+ if (trimmed.match(/^(\d+[\.\)]|\*|-|•)|^(feat|fix|docs|style|refactor|test|chore|perf|ci|build|revert)(\(.*?\))?:/)) {
1178
+ if (currentSuggestion) {
1179
+ suggestions.push(currentSuggestion.trim());
1180
+ }
1181
+ // Clean up the line (remove numbering/bullets)
1182
+ currentSuggestion = trimmed.replace(/^(\d+[\.\)]|\*|-|•)\s*/, '');
1183
+ } else if (currentSuggestion && trimmed.length > 0) {
1184
+ // Add to current suggestion (body content)
1185
+ currentSuggestion += '\n' + trimmed;
1186
+ }
1187
+ }
1188
+
1189
+ // Add the last suggestion
1190
+ if (currentSuggestion) {
1191
+ suggestions.push(currentSuggestion.trim());
1192
+ }
1193
+
1194
+ // Filter valid suggestions
1195
+ return suggestions
1196
+ .filter(s => s.length > 10 && s.includes(':'))
1197
+ .slice(0, 3); // Limit to 3 suggestions
1198
+ }
730
1199
  }