Skip to content

Commit

Permalink
feat: show multiple options (#64)
Browse files Browse the repository at this point in the history
  • Loading branch information
privatenumber committed Feb 16, 2023
1 parent 9ec7aee commit 68fc8ad
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 12 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
"@types/ini": "^1.3.31",
"@types/inquirer": "^9.0.3",
"@types/node": "^18.13.0",
"cleye": "^1.3.2",
"eslint": "^8.34.0",
"execa": "^7.0.0",
"ini": "^3.0.1",
Expand Down
17 changes: 17 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

61 changes: 51 additions & 10 deletions src/cli.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import { execa } from 'execa';
import {
black, green, red, bgCyan,
black, dim, green, red, bgCyan,
} from 'kolorist';
import {
intro, outro, spinner, confirm, isCancel,
intro, outro, spinner, select, confirm, isCancel,
} from '@clack/prompts';
import { cli } from 'cleye';
import { description, version } from '../package.json';
import {
getConfig,
assertGitRepo,
Expand All @@ -13,6 +15,25 @@ import {
generateCommitMessage,
} from './utils.js';

const argv = cli({
name: 'aicommits',

version,

flags: {
generate: {
type: Number,
description: 'Number of messages to generate. (Warning: generating multiple costs more)',
alias: 'g',
default: 1,
},
},

help: {
description,
},
});

(async () => {
intro(bgCyan(black(' aicommits ')));

Expand All @@ -38,16 +59,36 @@ import {

const s = spinner();
s.start('The AI is analyzing your changes');
const message = await generateCommitMessage(OPENAI_KEY, staged.diff);
s.stop('The commit message is ready for review');
const messages = await generateCommitMessage(
OPENAI_KEY,
staged.diff,
argv.flags.generate,
);
s.stop('Changes analyzed');

let message;
if (messages.length === 1) {
[message] = messages;
const confirmed = await confirm({
message: `Use this commit message?\n\n ${message}\n`,
});

if (!confirmed || isCancel(confirmed)) {
outro('Commit cancelled');
return;
}
} else {
const selected = await select({
message: `Pick a commit message to use: ${dim('(Ctrl+c to exit)')}`,
options: messages.map(value => ({ label: value, value })),
});

const confirmed = await confirm({
message: `Would you like to commit with this message:\n\n ${message}\n`,
});
if (isCancel(selected)) {
outro('Commit cancelled');
return;
}

if (!confirmed || isCancel(confirmed)) {
outro('Commit cancelled');
return;
message = selected;
}

await execa('git', ['commit', '-m', message]);
Expand Down
9 changes: 7 additions & 2 deletions src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,11 +60,14 @@ export const getStagedDiff = async () => {

export const getDetectedMessage = (files: string[]) => `Detected ${files.length.toLocaleString()} staged file${files.length > 1 ? 's' : ''}`;

const sanitizeMessage = (message: string) => message.trim().replace(/[\n\r]/g, '').replace(/(\w)\.$/, '$1');

const promptTemplate = 'Write an insightful but concise Git commit message in a complete sentence in present tense for the following diff without prefacing it with anything:';

export const generateCommitMessage = async (
apiKey: string,
diff: string,
completions: number,
) => {
const prompt = `${promptTemplate}\n${diff}`;

Expand All @@ -84,10 +87,12 @@ export const generateCommitMessage = async (
presence_penalty: 0,
max_tokens: 200,
stream: false,
n: 1,
n: completions,
});

return completion.data.choices[0].text!.trim().replace(/[\n\r]/g, '').replace(/(\w)\.$/, '$1');
return completion.data.choices
.filter(choice => choice.text)
.map(choice => sanitizeMessage(choice.text!));
} catch (error) {
const errorAsAny = error as any;
errorAsAny.message = `OpenAI API Error: ${errorAsAny.message} - ${errorAsAny.response.statusText}`;
Expand Down

0 comments on commit 68fc8ad

Please sign in to comment.