gims 0.6.4 β†’ 0.6.6

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
@@ -1,5 +1,34 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.6.6] - 2025-10-26
4
+
5
+ ### πŸ”§ Improvements
6
+ - **Removed commit message length restriction**: AI can now generate commit messages of any length (no more `...` truncation at 72 chars)
7
+ - **Added confirmation prompt for local heuristics**: When no AI provider is configured, the tool now asks for confirmation `[Y/n]` before committing
8
+ - Default is `Y` (just press Enter to accept)
9
+ - Warning message clearly indicates "local heuristics" instead of AI
10
+ - Can be bypassed with `--yes` flag for automation
11
+ - **Better user awareness**: Users are now informed when local heuristics are used instead of AI
12
+
13
+ ### πŸ“š User Experience
14
+ - More transparent about when AI is used vs. local pattern matching
15
+ - Safer commits when API keys are not configured
16
+
17
+ ---
18
+
19
+ ## [0.6.5] - 2025-10-20
20
+
21
+ ### πŸ”§ Command Behavior Updated
22
+ - **`g a` (amend) default behavior changed**: Now keeps the original commit message by default (`--no-edit`)
23
+ - **New `--edit` flag**: Use `g a --edit` to generate a new AI commit message
24
+ - **Simpler workflow**: `g a` simply merges current changes into previous commit without editing the message
25
+
26
+ ### πŸ“š Documentation Updates
27
+ - Updated all documentation to reflect the new amend behavior
28
+ - Clarified that `g a` merges changes while keeping the original message
29
+
30
+ ---
31
+
3
32
  ## [0.6.4] - 2025-10-19
4
33
 
5
34
  ### πŸ”§ Command Aliases Fixed
package/README.md CHANGED
@@ -36,7 +36,7 @@ g o # AI commit + push
36
36
  | `g ls` | Commit history (short) |
37
37
  | `g ll` | Commit history (detailed) |
38
38
  | `g h` | Commit history (alias for ls) |
39
- | `g a` | Smart amend |
39
+ | `g a` | Amend previous commit (keeps message) |
40
40
 
41
41
  ## πŸ€– AI Models
42
42
 
package/bin/gims.js CHANGED
@@ -90,7 +90,31 @@ async function safeLog() {
90
90
 
91
91
 
92
92
  async function generateCommitMessage(rawDiff, options = {}) {
93
- return await aiProvider.generateCommitMessage(rawDiff, options);
93
+ const result = await aiProvider.generateCommitMessage(rawDiff, options);
94
+ // Return both message and whether local heuristics were used
95
+ return result;
96
+ }
97
+
98
+ async function confirmCommit(message, isLocalHeuristic) {
99
+ if (!isLocalHeuristic) return true; // No confirmation needed for AI-generated messages
100
+
101
+ const readline = require('readline');
102
+ const rl = readline.createInterface({
103
+ input: process.stdin,
104
+ output: process.stdout
105
+ });
106
+
107
+ console.log(color.yellow('\n⚠️ No AI provider configured - using local heuristics'));
108
+ console.log(`Suggested commit: "${message}"`);
109
+
110
+ return new Promise((resolve) => {
111
+ rl.question('Proceed with this commit? [Y/n]: ', (answer) => {
112
+ rl.close();
113
+ const trimmed = answer.trim().toLowerCase();
114
+ // Default to 'yes' if empty (just Enter pressed)
115
+ resolve(trimmed === '' || trimmed === 'y' || trimmed === 'yes');
116
+ });
117
+ });
94
118
  }
95
119
 
96
120
  async function resolveCommit(input) {
@@ -311,7 +335,7 @@ program.command('help-quick').alias('q')
311
335
  console.log(` ${color.cyan('g ls')} List - Short commit history`);
312
336
  console.log(` ${color.cyan('g ll')} Large List - Detailed commit history`);
313
337
  console.log(` ${color.cyan('g h')} History - Alias for list`);
314
- console.log(` ${color.cyan('g a')} Amend - Smart amend with AI`);
338
+ console.log(` ${color.cyan('g a')} Amend - Merge changes to previous commit (keeps message)`);
315
339
  console.log(` ${color.cyan('g u')} Undo - Undo last commit\n`);
316
340
 
317
341
  console.log(color.bold('Quick Setup:'));
@@ -392,11 +416,19 @@ program.command('suggest').alias('sg')
392
416
  }
393
417
  } else {
394
418
  if (opts.progressIndicators) Progress.start('πŸ€– Analyzing changes');
395
- const msg = await generateCommitMessage(rawDiff, opts);
419
+ const result = await generateCommitMessage(rawDiff, opts);
396
420
  if (opts.progressIndicators) Progress.stop('');
421
+
422
+ const msg = result.message || result; // Handle both old and new format
423
+ const usedLocal = result.usedLocal || false;
424
+
425
+ // Warn if using local heuristics
426
+ if (usedLocal) {
427
+ console.log(color.yellow('⚠️ No AI provider configured - using local heuristics'));
428
+ }
397
429
 
398
430
  if (opts.json) {
399
- const out = { message: msg };
431
+ const out = { message: msg, usedLocalHeuristics: usedLocal };
400
432
  console.log(JSON.stringify(out));
401
433
  return;
402
434
  }
@@ -446,8 +478,11 @@ program.command('local').alias('l')
446
478
  }
447
479
 
448
480
  if (opts.progressIndicators) Progress.start('πŸ€– Generating commit message');
449
- const msg = await generateCommitMessage(rawDiff, opts);
481
+ const result = await generateCommitMessage(rawDiff, opts);
450
482
  if (opts.progressIndicators) Progress.stop('');
483
+
484
+ const msg = result.message || result; // Handle both old and new format
485
+ const usedLocal = result.usedLocal || false;
451
486
 
452
487
  if (opts.dryRun) {
453
488
  console.log(color.yellow('[dry-run] Would commit with message:'));
@@ -455,6 +490,15 @@ program.command('local').alias('l')
455
490
  return;
456
491
  }
457
492
 
493
+ // Ask for confirmation if using local heuristics (unless --yes flag is set)
494
+ if (usedLocal && !opts.yes) {
495
+ const confirmed = await confirmCommit(msg, true);
496
+ if (!confirmed) {
497
+ Progress.info('Commit cancelled');
498
+ return;
499
+ }
500
+ }
501
+
458
502
  if (opts.amend) {
459
503
  await git.raw(['commit', '--amend', '-m', msg]);
460
504
  Progress.success(`Amended commit: "${msg}"`);
@@ -496,8 +540,11 @@ program.command('online').alias('o')
496
540
  }
497
541
 
498
542
  if (opts.progressIndicators) Progress.start('πŸ€– Generating commit message');
499
- const msg = await generateCommitMessage(rawDiff, opts);
543
+ const result = await generateCommitMessage(rawDiff, opts);
500
544
  if (opts.progressIndicators) Progress.stop('');
545
+
546
+ const msg = result.message || result; // Handle both old and new format
547
+ const usedLocal = result.usedLocal || false;
501
548
 
502
549
  if (opts.dryRun) {
503
550
  console.log(color.yellow('[dry-run] Would commit & push with message:'));
@@ -505,6 +552,15 @@ program.command('online').alias('o')
505
552
  return;
506
553
  }
507
554
 
555
+ // Ask for confirmation if using local heuristics (unless --yes flag is set)
556
+ if (usedLocal && !opts.yes) {
557
+ const confirmed = await confirmCommit(msg, true);
558
+ if (!confirmed) {
559
+ Progress.info('Commit cancelled');
560
+ return;
561
+ }
562
+ }
563
+
508
564
  Progress.info('Committing changes...');
509
565
  if (opts.amend) {
510
566
  await git.raw(['commit', '--amend', '-m', msg]);
@@ -701,8 +757,8 @@ program.command('stash')
701
757
  });
702
758
 
703
759
  program.command('amend').alias('a')
704
- .description('Stage all changes and amend last commit')
705
- .option('--no-edit', 'Keep existing commit message')
760
+ .description('Stage all changes and amend last commit (keeps message)')
761
+ .option('--edit', 'Generate new AI commit message')
706
762
  .action(async (cmdOptions) => {
707
763
  await ensureRepo();
708
764
  try {
@@ -721,17 +777,31 @@ program.command('amend').alias('a')
721
777
  return;
722
778
  }
723
779
 
724
- if (cmdOptions.noEdit) {
725
- await git.raw(['commit', '--amend', '--no-edit']);
726
- Progress.success('Amended last commit with staged changes');
727
- } else {
780
+ if (cmdOptions.edit) {
728
781
  // Generate new message for amend
782
+ const opts = getOpts();
729
783
  Progress.start('πŸ€– Generating updated commit message');
730
- const newMessage = await generateCommitMessage(rawDiff, getOpts());
784
+ const result = await generateCommitMessage(rawDiff, opts);
731
785
  Progress.stop('');
732
786
 
787
+ const newMessage = result.message || result; // Handle both old and new format
788
+ const usedLocal = result.usedLocal || false;
789
+
790
+ // Ask for confirmation if using local heuristics (unless --yes flag is set)
791
+ if (usedLocal && !opts.yes) {
792
+ const confirmed = await confirmCommit(newMessage, true);
793
+ if (!confirmed) {
794
+ Progress.info('Amend cancelled');
795
+ return;
796
+ }
797
+ }
798
+
733
799
  await git.raw(['commit', '--amend', '-m', newMessage]);
734
800
  Progress.success(`Amended commit: "${newMessage}"`);
801
+ } else {
802
+ // Default: Keep existing message (--no-edit)
803
+ await git.raw(['commit', '--amend', '--no-edit']);
804
+ Progress.success('Amended last commit with staged changes (kept original message)');
735
805
  }
736
806
  } catch (e) {
737
807
  handleError('Amend error', e);
@@ -46,7 +46,7 @@ class AIProviderManager {
46
46
  return this.cache.get(cacheKey);
47
47
  }
48
48
 
49
- setCache(cacheKey, result) {
49
+ setCache(cacheKey, result, usedLocal = false) {
50
50
  if (!this.config.cacheEnabled) return;
51
51
 
52
52
  if (this.cache.size >= this.maxCacheSize) {
@@ -56,6 +56,7 @@ class AIProviderManager {
56
56
 
57
57
  this.cache.set(cacheKey, {
58
58
  result,
59
+ usedLocal,
59
60
  timestamp: Date.now()
60
61
  });
61
62
  }
@@ -129,7 +130,7 @@ class AIProviderManager {
129
130
  const cached = this.getFromCache(cacheKey);
130
131
  if (cached && Date.now() - cached.timestamp < 3600000) { // 1 hour cache
131
132
  if (verbose) Progress.info('Using cached result');
132
- return cached.result;
133
+ return { message: cached.result, usedLocal: cached.usedLocal || false };
133
134
  }
134
135
 
135
136
  const providerChain = this.buildProviderChain(preferredProvider);
@@ -140,16 +141,16 @@ class AIProviderManager {
140
141
 
141
142
  if (provider === 'local') {
142
143
  const result = await this.generateLocalHeuristic(diff, options);
143
- this.setCache(cacheKey, result);
144
- return result;
144
+ this.setCache(cacheKey, result, true);
145
+ return { message: result, usedLocal: true };
145
146
  }
146
147
 
147
148
  const prompt = this.buildPrompt(diff, { conventional, body });
148
149
  const result = await this.generateWithProvider(provider, prompt, options);
149
150
  const cleaned = this.cleanCommitMessage(result, { body });
150
151
 
151
- this.setCache(cacheKey, cleaned);
152
- return cleaned;
152
+ this.setCache(cacheKey, cleaned, false);
153
+ return { message: cleaned, usedLocal: false };
153
154
 
154
155
  } catch (error) {
155
156
  if (verbose) Progress.warning(`${provider} failed: ${error.message}`);
@@ -159,8 +160,8 @@ class AIProviderManager {
159
160
 
160
161
  // Final fallback
161
162
  const fallback = 'Update project files';
162
- this.setCache(cacheKey, fallback);
163
- return fallback;
163
+ this.setCache(cacheKey, fallback, true);
164
+ return { message: fallback, usedLocal: true };
164
165
  }
165
166
 
166
167
  buildProviderChain(preferred) {
@@ -213,7 +214,7 @@ class AIProviderManager {
213
214
  let subject = (lines[0] || '').replace(/\s{2,}/g, ' ').replace(/[\s:,.!;]+$/g, '').trim();
214
215
 
215
216
  if (subject.length === 0) subject = 'Update project code';
216
- if (subject.length > 72) subject = subject.substring(0, 69) + '...';
217
+ // No length restriction - allow AI to generate full commit messages
217
218
 
218
219
  if (!options.body) return subject;
219
220
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gims",
3
- "version": "0.6.4",
3
+ "version": "0.6.6",
4
4
  "description": "Git Made Simple – AI‑powered git helper using Gemini / OpenAI",
5
5
  "author": "S41R4J",
6
6
  "license": "MIT",
@@ -1,77 +0,0 @@
1
- # πŸš€ GIMS Quick Reference
2
-
3
- ## Single-Letter Workflow Commands
4
-
5
- ```bash
6
- g s # Status - Enhanced git status with AI insights
7
- g i # Init - Initialize a new Git repository
8
- g p # Preview - See what will be committed
9
- g l # Local - AI commit locally
10
- g o # Online - AI commit + push
11
- g ls # List - Short commit history
12
- g ll # Large List - Detailed commit history
13
- g h # History - Alias for list
14
- g a # Amend - Smart amend with AI
15
- g u # Undo - Undo last commit
16
- ```
17
-
18
- ## Quick Setup
19
-
20
- ```bash
21
- # Choose your AI provider (one-time setup)
22
- g setup --api-key gemini # πŸš€ Recommended: Fast & free
23
- g setup --api-key openai # πŸ’Ž High quality
24
- g setup --api-key groq # ⚑ Ultra fast
25
-
26
- # Or run full setup wizard
27
- g setup
28
- ```
29
-
30
- ## Essential Workflow
31
-
32
- ```bash
33
- # 1. Check what's changed
34
- g s
35
-
36
- # 2. Commit with AI (choose one)
37
- g int # Interactive mode (guided)
38
- g o # One-command: commit + push
39
- g l # Local commit only
40
-
41
- # 3. View history
42
- g ls # Recent commits (short)
43
- g ll # Recent commits (detailed)
44
- g h # Same as g ls
45
- ```
46
-
47
- ## Default AI Models
48
-
49
- - **Gemini**: `gemini-2.5-flash` (Fast, free, recommended)
50
- - **OpenAI**: `gpt-5` (Latest GPT model)
51
- - **Groq**: `groq/compound` (Ultra-fast inference)
52
-
53
- ## Pro Tips
54
-
55
- ```bash
56
- g sg --multiple # Get 3 AI suggestions
57
- g p # Preview before committing
58
- g a # Smart amend with new AI message
59
- g sync --rebase # Smart sync with rebase
60
- g stash # Stash with AI description
61
- ```
62
-
63
- ## Configuration
64
-
65
- ```bash
66
- g config --list # View all settings
67
- g config --set conventional=true # Enable conventional commits
68
- g config --set autoStage=true # Auto-stage changes
69
- g config --set provider=gemini # Set AI provider
70
- ```
71
-
72
- ## Help
73
-
74
- ```bash
75
- g --help # All commands
76
- g q # This quick reference
77
- ```