-
Notifications
You must be signed in to change notification settings - Fork 11
/
Copy pathautocommit.js
executable file
·114 lines (93 loc) · 3.57 KB
/
autocommit.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
#!/usr/bin/env bun
import { execSync, spawn } from "child_process";
import rc from 'rc';
import defaultConfig from './config.js';
import { OpenAI } from "openai";
import {calculateMaxTokens, getModelContextSize} from "./count_tokens.js";
const config = rc(
'git-aicommit',
{
...defaultConfig,
openAiKey: process.env.OPENAI_API_KEY,
azureOpenAIApiKey: process.env.AZURE_OPENAI_API_KEY
},
);
try {
execSync(
'git rev-parse --is-inside-work-tree',
{encoding: 'utf8', stdio: 'ignore'}
);
} catch (e) {
console.error("This is not a git repository");
process.exit(1);
}
if (!config.openAiKey && !config.azureOpenAiKey) {
console.error("Please set OPENAI_API_KEY or AZURE_OPENAI_API_KEY");
process.exit(1);
}
// if any settings related to AZURE are set, if there are items that are not set, will error.
if (config.azureOpenAiKey && !(
config.azureOpenAiInstanceName && config.azureOpenAiDeploymentName && config.azureOpenAiVersion
)){
console.error("Please set AZURE_OPENAI_API_KEY, AZURE_OPENAI_API_INSTANCE_NAME, AZURE_OPENAI_API_DEPLOYMENT_NAME, AZURE_OPENAI_API_VERSION when Azure OpenAI Service.");
process.exit(1);
}
const excludeFromDiff = config.excludeFromDiff || [];
const diffFilter = config.diffFilter || 'ACMRTUXB';
const diffCommand = `git diff --staged \
--no-ext-diff \
--diff-filter=${diffFilter} \
-- ${excludeFromDiff.map(
(pattern) => `':(exclude)${pattern}'`
).join(' ')}
`;
let diff = execSync(diffCommand, {encoding: 'utf8'});
if (!diff) {
console.error("Diff seems empty. Please commit manually.");
process.exit(1);
}
const openai = new OpenAI({
apiKey: config.openAiKey,
baseURL: config.azureOpenAiKey ? `https://${config.azureOpenAiInstanceName}.openai.azure.com/openai/deployments/${config.azureOpenAiDeploymentName}` : undefined,
defaultHeaders: config.azureOpenAiKey ? { 'api-key': config.azureOpenAiKey } : undefined
});
async function getChatCompletion(messages) {
const response = await openai.chat.completions.create({
model: config.modelName || 'gpt-4o-mini',
messages: messages,
temperature: config.temperature,
max_tokens: config.maxTokens,
});
return response.choices[0].message.content.trim();
}
const systemMessage = { role: "system", content: config.systemMessagePromptTemplate };
const userMessage = { role: "user", content: config.humanPromptTemplate.replace("{diff}", diff).replace("{language}", config.language) };
const chatMessages = [systemMessage, userMessage];
const tokenCount = await calculateMaxTokens({
prompt: diff,
modelName: config.modelName || 'gpt-4o-mini'
});
const contextSize = getModelContextSize(config.modelName || 'gpt-4o-mini');
if (tokenCount > contextSize) {
console.log('Diff is too long. Please lower the amount of changes in the commit or switch to a model with bigger context size');
process.exit(1);
}
const messages = [
{ role: "system", content: config.systemMessagePromptTemplate },
{ role: "user", content: config.humanPromptTemplate.replace("{diff}", diff).replace("{language}", config.language) }
];
const commitMessage = await getChatCompletion(messages);
if (!config.autocommit) {
console.log(`Autocommit is disabled. Here is the message:\n ${commitMessage}`);
} else {
console.log(`Committing with following message:\n ${commitMessage}`);
execSync(
`git commit -m "${commitMessage.replace(/"/g, '')}"`,
{encoding: 'utf8'}
);
}
if (config.openCommitTextEditor) {
spawn('git', ['commit', '--amend'], {
stdio: 'inherit'
});
}