commic 1.0.0 → 1.0.2

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.
@@ -32,14 +32,31 @@ export class MainOrchestrator {
32
32
  const repositoryPath = options.path || '.';
33
33
  const repository = await this.findAndValidateRepository(repositoryPath);
34
34
 
35
+ // Step 2.5: Stage all changes
36
+ await this.stageAllChanges(repository.rootPath);
37
+
35
38
  // Step 3: Get Git diff
36
39
  const diff = await this.getGitDiff(repository.rootPath);
37
40
 
38
41
  // Step 4: Generate commit suggestions
39
- const suggestions = await this.generateSuggestions(config, diff);
42
+ let suggestions = await this.generateSuggestions(config, diff);
43
+ let customInstruction: string | undefined;
44
+
45
+ // Step 5: Let user select a commit message (with regenerate option)
46
+ let selectedIndex = await this.uiManager.promptForCommitSelection(suggestions);
40
47
 
41
- // Step 5: Let user select a commit message
42
- const selectedIndex = await this.uiManager.promptForCommitSelection(suggestions);
48
+ // Handle regenerate with prompt loop
49
+ while (selectedIndex === -2) {
50
+ // Get custom instruction from user
51
+ customInstruction = await this.uiManager.promptForCustomInstruction();
52
+
53
+ // Regenerate suggestions with custom instruction
54
+ this.uiManager.newLine();
55
+ suggestions = await this.generateSuggestions(config, diff, customInstruction);
56
+
57
+ // Prompt again with new suggestions
58
+ selectedIndex = await this.uiManager.promptForCommitSelection(suggestions);
59
+ }
43
60
 
44
61
  // Handle cancellation
45
62
  if (selectedIndex === -1) {
@@ -47,10 +64,7 @@ export class MainOrchestrator {
47
64
  return;
48
65
  }
49
66
 
50
- // Step 6: Stage changes if needed
51
- await this.stageChangesIfNeeded(repository.rootPath, diff);
52
-
53
- // Step 7: Execute commit
67
+ // Step 6: Execute commit (changes already staged)
54
68
  const commitHash = await this.executeCommit(
55
69
  repository.rootPath,
56
70
  suggestions[selectedIndex].message
@@ -181,18 +195,19 @@ export class MainOrchestrator {
181
195
  * Generate commit message suggestions using AI
182
196
  * @param config Configuration with API key
183
197
  * @param diff Git diff
198
+ * @param customInstruction Optional custom instruction for regeneration
184
199
  * @returns Array of suggestions
185
200
  */
186
- private async generateSuggestions(config: Config, diff: any) {
201
+ private async generateSuggestions(config: Config, diff: any, customInstruction?: string) {
187
202
  this.uiManager.newLine();
188
203
  this.uiManager.showSectionHeader('🤖 AI Generation');
189
- this.uiManager.showAIGenerationInfo(config.model, 4);
204
+ this.uiManager.showAIGenerationInfo(config.model);
190
205
 
191
206
  const spinner = this.uiManager.showLoading(' Generating commit messages...');
192
207
 
193
208
  try {
194
209
  const aiService = new AIService(config.apiKey, config.model);
195
- const suggestions = await aiService.generateCommitMessages(diff, 4);
210
+ const suggestions = await aiService.generateCommitMessages(diff, customInstruction);
196
211
 
197
212
  spinner.succeed(` Generated ${suggestions.length} suggestions`);
198
213
  this.uiManager.newLine();
@@ -205,22 +220,18 @@ export class MainOrchestrator {
205
220
  }
206
221
 
207
222
  /**
208
- * Stage changes if there are unstaged changes
223
+ * Stage all changes in the repository
209
224
  * @param repoPath Repository root path
210
- * @param diff Git diff
211
225
  */
212
- private async stageChangesIfNeeded(repoPath: string, diff: any): Promise<void> {
213
- if (diff.unstaged && diff.unstaged.length > 0) {
226
+ private async stageAllChanges(repoPath: string): Promise<void> {
227
+ const spinner = this.uiManager.showLoading('Staging all changes...');
228
+ try {
229
+ await this.gitService.stageAll(repoPath);
230
+ spinner.succeed('All changes staged');
214
231
  this.uiManager.newLine();
215
- const spinner = this.uiManager.showLoading('Staging changes...');
216
- try {
217
- await this.gitService.stageAll(repoPath);
218
- spinner.succeed('Changes staged');
219
- this.uiManager.newLine();
220
- } catch (error) {
221
- spinner.fail('Failed to stage changes');
222
- throw error;
223
- }
232
+ } catch (error) {
233
+ spinner.fail('Failed to stage changes');
234
+ throw error;
224
235
  }
225
236
  }
226
237
 
@@ -241,14 +241,11 @@ export class UIManager {
241
241
  /**
242
242
  * Display AI generation info
243
243
  * @param model Model name being used
244
- * @param suggestionCount Number of suggestions generated
245
244
  */
246
- showAIGenerationInfo(model: string, suggestionCount: number): void {
245
+ showAIGenerationInfo(model: string): void {
247
246
  console.log(this.colors.muted(` 🤖 Model: ${chalk.cyan.bold(model)}`));
248
247
  console.log(
249
- this.colors.muted(
250
- ` 📝 Generating ${chalk.cyan.bold(suggestionCount)} commit message suggestions...`
251
- )
248
+ this.colors.muted(` 📝 Generating ${chalk.cyan.bold(5)} commit message suggestions...`)
252
249
  );
253
250
  console.log();
254
251
  }
@@ -291,7 +288,7 @@ export class UIManager {
291
288
  name: 'model',
292
289
  message: 'Select Gemini model:',
293
290
  choices: models.map((model) => {
294
- if (model === 'gemini-2.5-flash') {
291
+ if (model === 'gemini-3-flash-preview') {
295
292
  return {
296
293
  name: `${model} ${chalk.gray('(stable)')}`,
297
294
  value: model,
@@ -359,6 +356,13 @@ export class UIManager {
359
356
  };
360
357
  });
361
358
 
359
+ // Add regenerate with prompt option
360
+ choices.push({
361
+ name: chalk.cyan('🔄 Regenerate with prompt'),
362
+ value: -2,
363
+ short: 'Regenerate',
364
+ });
365
+
362
366
  // Add cancel option
363
367
  choices.push({
364
368
  name: chalk.red("✖ Cancel (don't commit)"),
@@ -377,8 +381,8 @@ export class UIManager {
377
381
  },
378
382
  ]);
379
383
 
380
- // Show preview of selected message if not cancelled
381
- if (answer.selection !== -1) {
384
+ // Show preview of selected message if not cancelled and not regenerate
385
+ if (answer.selection !== -1 && answer.selection !== -2) {
382
386
  this.newLine();
383
387
  this.showSectionHeader('✅ Selected commit message');
384
388
  console.log();
@@ -417,4 +421,26 @@ export class UIManager {
417
421
 
418
422
  return answer.confirmed;
419
423
  }
424
+
425
+ /**
426
+ * Prompt user for custom instruction to regenerate commit messages
427
+ * @returns Custom instruction string or empty string if cancelled
428
+ */
429
+ async promptForCustomInstruction(): Promise<string> {
430
+ const answer = await inquirer.prompt([
431
+ {
432
+ type: 'input',
433
+ name: 'instruction',
434
+ message: 'Enter your instruction for regenerating commit messages:',
435
+ validate: (input: string) => {
436
+ if (!input || input.trim().length === 0) {
437
+ return 'Instruction cannot be empty';
438
+ }
439
+ return true;
440
+ },
441
+ },
442
+ ]);
443
+
444
+ return answer.instruction.trim();
445
+ }
420
446
  }