gims 0.6.5 β†’ 0.6.7

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,30 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.6.7] - 2025-10-26
4
+
5
+ ### πŸ”§ Fixes
6
+ - **Added `-v` flag for version**: Now `g -v` or `gims -v` shows the version number
7
+ - **Renamed command**: Changed `help-quick` to `quick-help` (alias `q` still works)
8
+ - **Added `push` command**: Now `g push` or `gims push` works as a standalone command
9
+
10
+ ---
11
+
12
+ ## [0.6.6] - 2025-10-26
13
+
14
+ ### πŸ”§ Improvements
15
+ - **Removed commit message length restriction**: AI can now generate commit messages of any length (no more `...` truncation at 72 chars)
16
+ - **Added confirmation prompt for local heuristics**: When no AI provider is configured, the tool now asks for confirmation `[Y/n]` before committing
17
+ - Default is `Y` (just press Enter to accept)
18
+ - Warning message clearly indicates "local heuristics" instead of AI
19
+ - Can be bypassed with `--yes` flag for automation
20
+ - **Better user awareness**: Users are now informed when local heuristics are used instead of AI
21
+
22
+ ### πŸ“š User Experience
23
+ - More transparent about when AI is used vs. local pattern matching
24
+ - Safer commits when API keys are not configured
25
+
26
+ ---
27
+
3
28
  ## [0.6.5] - 2025-10-20
4
29
 
5
30
  ### πŸ”§ Command Behavior Updated
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) {
@@ -113,7 +137,7 @@ async function hasChanges() {
113
137
  program
114
138
  .name('gims')
115
139
  .alias('g')
116
- .version(require('../package.json').version)
140
+ .version(require('../package.json').version, '-v, --version', 'Output the version number')
117
141
  .option('--provider <name>', 'AI provider: auto|openai|gemini|groq|none')
118
142
  .option('--model <name>', 'Model identifier for provider')
119
143
  .option('--staged-only', 'Use only staged changes (default for suggest)')
@@ -297,7 +321,7 @@ program.command('config')
297
321
  }
298
322
  });
299
323
 
300
- program.command('help-quick').alias('q')
324
+ program.command('quick-help').alias('q')
301
325
  .description('Show quick reference for main commands')
302
326
  .action(() => {
303
327
  console.log(color.bold('πŸš€ GIMS Quick Reference\n'));
@@ -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]);
@@ -592,6 +648,18 @@ program.command('pull')
592
648
  catch (e) { handleError('Pull error', e); }
593
649
  });
594
650
 
651
+ program.command('push')
652
+ .description('Push commits to remote')
653
+ .action(async () => {
654
+ await ensureRepo();
655
+ try {
656
+ Progress.info('Pushing to remote...');
657
+ await git.push();
658
+ Progress.success('Pushed to remote');
659
+ }
660
+ catch (e) { handleError('Push error', e); }
661
+ });
662
+
595
663
  program.command('sync')
596
664
  .description('Smart sync: pull + rebase/merge')
597
665
  .option('--rebase', 'Use rebase instead of merge')
@@ -723,10 +791,23 @@ program.command('amend').alias('a')
723
791
 
724
792
  if (cmdOptions.edit) {
725
793
  // Generate new message for amend
794
+ const opts = getOpts();
726
795
  Progress.start('πŸ€– Generating updated commit message');
727
- const newMessage = await generateCommitMessage(rawDiff, getOpts());
796
+ const result = await generateCommitMessage(rawDiff, opts);
728
797
  Progress.stop('');
729
798
 
799
+ const newMessage = result.message || result; // Handle both old and new format
800
+ const usedLocal = result.usedLocal || false;
801
+
802
+ // Ask for confirmation if using local heuristics (unless --yes flag is set)
803
+ if (usedLocal && !opts.yes) {
804
+ const confirmed = await confirmCommit(newMessage, true);
805
+ if (!confirmed) {
806
+ Progress.info('Amend cancelled');
807
+ return;
808
+ }
809
+ }
810
+
730
811
  await git.raw(['commit', '--amend', '-m', newMessage]);
731
812
  Progress.success(`Amended commit: "${newMessage}"`);
732
813
  } else {
@@ -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.5",
3
+ "version": "0.6.7",
4
4
  "description": "Git Made Simple – AI‑powered git helper using Gemini / OpenAI",
5
5
  "author": "S41R4J",
6
6
  "license": "MIT",
@@ -1,78 +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 - Merge changes into previous commit (keeps message)
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 # Amend: merge changes to previous commit (keeps message)
59
- g a --edit # Amend with new AI-generated message
60
- g sync --rebase # Smart sync with rebase
61
- g stash # Stash with AI description
62
- ```
63
-
64
- ## Configuration
65
-
66
- ```bash
67
- g config --list # View all settings
68
- g config --set conventional=true # Enable conventional commits
69
- g config --set autoStage=true # Auto-stage changes
70
- g config --set provider=gemini # Set AI provider
71
- ```
72
-
73
- ## Help
74
-
75
- ```bash
76
- g --help # All commands
77
- g q # This quick reference
78
- ```