git-aicommit 4.0.0 → 5.0.0

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.
@@ -11,7 +11,7 @@ jobs:
11
11
  - uses: actions/checkout@v3
12
12
  - uses: actions/setup-node@v3
13
13
  with:
14
- node-version: 16
14
+ node-version: 18
15
15
  registry-url: https://registry.npmjs.org/
16
16
  - run: npm ci
17
17
  - run: npm publish
package/README.md CHANGED
@@ -34,28 +34,30 @@ touch $HOME/.git-aicommitrc
34
34
 
35
35
  ```js
36
36
  // $HOME/.git-aicommitrc
37
- module.exports = {
37
+ export default {
38
38
  openAiKey: process.env.OPENAI_API_KEY,
39
39
  addAllChangesBeforeCommit: true,
40
40
  autocommit: true,
41
41
  openCommitTextEditor: false,
42
- promptBeforeDiff: 'Read the following git diff for a multiple files:',
43
- promptAfterDiff: 'Generate 1 to 3 paragraphs to explain this diff to a human without mentioning changes themselves:',
42
+ language: 'english',
43
+ systemMessagePromptTemplate: '' +
44
+ 'You are expert AI, your job is to write clear and concise Git commit messages.' +
45
+ 'Your responsibility is to ensure that these messages accurately describe the changes made in each commit,' +
46
+ 'follow established guidelines. Provide a clear history of changes to the codebase.' +
47
+ 'Write 1-2 sentences. Output only the commit message without comments or other text.',
48
+ humanPromptTemplate: '' +
49
+ 'Read the following git diff for a multiple files and ' +
50
+ 'write 1-2 sentences commit message in {language}' +
51
+ 'without mentioning lines or files:\n' +
52
+ '{diff}',
44
53
  excludeFromDiff: [
45
- '*.lock'
54
+ '*.lock', '*.lockb'
46
55
  ],
47
56
  diffFilter: 'ACMRTUXB',
48
57
  completionPromptParams: {
49
- model: "text-davinci-002",
50
- max_tokens: 500,
51
- temperature: 0.2,
52
- top_p: 1,
53
- presence_penalty: 0,
54
- frequency_penalty: 0,
55
- best_of: 1,
56
- n: 1,
57
- stream: false,
58
- stop: ["\n\n\n"],
58
+ model: "gpt-3.5-turbo",
59
+ temperature: 0.0,
60
+ maxTokens: 1000,
59
61
  }
60
62
  }
61
63
  ```
package/autocommit.js CHANGED
@@ -1,13 +1,19 @@
1
- #!/usr/bin/env bun
1
+ #!/usr/bin/env node
2
2
 
3
3
  import { execSync, spawn } from "child_process";
4
4
  import rc from 'rc';
5
- import { ChatOpenAI } from "langchain/chat_models";
6
- import {ChatPromptTemplate, HumanMessagePromptTemplate, SystemMessagePromptTemplate} from "langchain/prompts";
5
+ import {
6
+ ChatPromptTemplate,
7
+ HumanMessagePromptTemplate,
8
+ PromptTemplate,
9
+ SystemMessagePromptTemplate
10
+ } from "langchain/prompts";
7
11
  import defaultConfig from './config.js';
8
- import dotenv from 'dotenv';
9
-
10
- dotenv.config();
12
+ import {RecursiveCharacterTextSplitter} from "langchain/text_splitter";
13
+ import {loadSummarizationChain} from "langchain/chains";
14
+ import {ChatOpenAI} from "langchain/chat_models/openai";
15
+ import {OpenAI} from "langchain/llms/openai";
16
+ import fs from "fs";
11
17
 
12
18
  const config = rc(
13
19
  'git-aicommit',
@@ -35,13 +41,14 @@ if (!config.openAiKey) {
35
41
  const excludeFromDiff = config.excludeFromDiff || [];
36
42
  const diffFilter = config.diffFilter || 'ACMRTUXB';
37
43
  const diffCommand = `git diff --staged \
44
+ --no-ext-diff \
38
45
  --diff-filter=${diffFilter} \
39
46
  -- "${excludeFromDiff.map(
40
47
  (pattern) => `:(exclude)${pattern}`
41
48
  ).join(' ')}"
42
49
  `;
43
50
 
44
- const diff = execSync(diffCommand, {encoding: 'utf8'});
51
+ let diff = execSync(diffCommand, {encoding: 'utf8'});
45
52
 
46
53
  if (!diff) {
47
54
  console.error("Diff seems empty. Please commit manually.");
@@ -50,18 +57,67 @@ if (!diff) {
50
57
 
51
58
  const openai = new ChatOpenAI({
52
59
  modelName: config.modelName,
53
- apiKey: config.openAiKey,
60
+ openAIApiKey: config.openAiKey,
54
61
  temperature: config.temperature,
55
62
  maxTokens: config.maxTokens,
56
63
  });
57
64
 
58
- const systemMessagePromptTemplate = SystemMessagePromptTemplate.fromTemplate(config.systemMessagePromptTemplate)
59
- const humanPromptTemplate = HumanMessagePromptTemplate.fromTemplate(config.humanPromptTemplate)
65
+ const systemMessagePromptTemplate = SystemMessagePromptTemplate.fromTemplate(
66
+ config.systemMessagePromptTemplate
67
+ );
68
+
69
+ const humanPromptTemplate = HumanMessagePromptTemplate.fromTemplate(
70
+ config.humanPromptTemplate
71
+ );
60
72
 
61
73
  const chatPrompt = ChatPromptTemplate.fromPromptMessages([
62
74
  systemMessagePromptTemplate,
63
75
  humanPromptTemplate,
64
- ])
76
+ ]);
77
+
78
+ if (diff.length > 2000) {
79
+ const filenameRegex = /^a\/(.+?)\s+b\/(.+?)/;
80
+ const diffByFiles = diff
81
+ .split('diff ' + '--git ') // Wierd string concat in order to avoid splitting on this line when using autocommit in this repo :)
82
+ .filter((fileDiff) => fileDiff.length > 0)
83
+ .map((fileDiff) => {
84
+ const match = fileDiff.match(filenameRegex);
85
+ const filename = match ? match[1] : 'Unknown file';
86
+
87
+ const content = fileDiff
88
+ .replaceAll(filename, '')
89
+ .replaceAll('a/ b/\n', '')
90
+
91
+ return chatPrompt
92
+ .formatMessages({
93
+ diff: content,
94
+ language: config.language,
95
+ })
96
+ .then((prompt) => {
97
+ return openai.call(prompt)
98
+ .then((res) => {
99
+ return {
100
+ filename: filename,
101
+ changes: res.text.trim(),
102
+ }
103
+ })
104
+ .catch((e) => {
105
+ console.error(`Error during OpenAI request: ${e.message}`);
106
+ process.exit(1);
107
+ });
108
+ });
109
+ });
110
+
111
+ // wait for all promises to resolve
112
+ const mergeChanges = await Promise.all(diffByFiles);
113
+
114
+ diff = mergeChanges
115
+ .map((fileDiff) => {
116
+ return `diff --git ${fileDiff.filename}\n${fileDiff.changes}`
117
+
118
+ })
119
+ .join('\n\n')
120
+ }
65
121
 
66
122
  const prompt = await chatPrompt.formatMessages({
67
123
  diff: diff,
@@ -69,6 +125,10 @@ const prompt = await chatPrompt.formatMessages({
69
125
  })
70
126
 
71
127
  const res = await openai.call(prompt)
128
+ .catch((e) => {
129
+ console.error(`Error during OpenAI request: ${e.message}`);
130
+ process.exit(1);
131
+ });
72
132
 
73
133
  const commitMessage = res.text.trim();
74
134
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "git-aicommit",
3
- "version": "4.0.0",
3
+ "version": "5.0.0",
4
4
  "description": "Generates auto commit messages with OpenAI GPT3 model",
5
5
  "main": "autocommit.js",
6
6
  "repository": "https://github.com/shanginn/autocommit",
@@ -8,10 +8,10 @@
8
8
  "license": "MIT",
9
9
  "type": "module",
10
10
  "dependencies": {
11
- "dotenv": "^16.0.2",
12
- "langchain": "^0.0.47",
13
- "openai": "^3.0.0",
14
- "rc": "1.2.8"
11
+ "@dqbd/tiktoken": "^1.0.6",
12
+ "langchain": "^0.0.59",
13
+ "openai": "^3.2.1",
14
+ "rc": "^1.2.8"
15
15
  },
16
16
  "preferGlobal": true,
17
17
  "bin": {