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 +25 -0
- package/bin/gims.js +89 -8
- package/bin/lib/ai/providers.js +10 -9
- package/package.json +1 -1
- package/QUICK_REFERENCE.md +0 -78
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
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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 {
|
package/bin/lib/ai/providers.js
CHANGED
|
@@ -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
|
-
|
|
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
package/QUICK_REFERENCE.md
DELETED
|
@@ -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
|
-
```
|